I want to use "static polymorphism" via CRTP to do something like the following:
template <typename T>
struct Base
{
double get_value() const { return ((T*)this)->_get_value(); }
protected:
~Base() {}
};
struct Derived1 : public Base<Derived1>
{
double value;
Derived1() : value(3.) {}
const double& _get_value() const { return value; }
};
struct Derived2 : public Base<Derived2>
{
double _get_value() const { return 5.; }
};
This works, but I'd also like that for the case of the object being instantiated as Derived1, get_value returns a const reference to the value instead of returning a copy. So in a way, a kind of "perfect forwarding" for return values.
I tried to declare get_value's return type like this:
template <typename T>
struct Base
{
decltype(std::declval<T>()._get_value()) get_value() const { return ((T*)this)->_get_value(); }
...
but unsurprisingly GCC complained that this is an invalid use of incomplete type 'struct Derived1'.
Is there any way to go around this?
Thank you in advance! :)
The reason why GCC is rejecting the proposed solution in the OP is that
Base<Derived1>is being instantiated beforeDerived1. This instantiation consists of an instantiation of the signatures of all member functions, but it doesn't instantiate the function bodies themselves.So we need to defer determination of the signature/return type of the member function until after
Derived1is visible.One way to do this is by deferring determination of the return type via
decltype(auto). This makes the return type dependent on the function body (which is not immediately instantiated). It's a C++14 feature, unfortunately.See https://godbolt.org/z/r1T56n
This is probably covered by dcl.spec.auto and temp.inst.
Alternatively, even in C++11, you can postpone determination of the return type by turning the function into a function template, dependent on some dummy parameter if necessary: