Consider the following:
template<typename Der>
struct Base {
// NOTE: if I replace the decltype(...) below with auto, code compiles
decltype(&Der::operator()) getCallOperator() const {
return &Der::operator();
}
};
struct Foo : Base<Foo> {
double operator()(int, int) const {
return 0.0;
}
};
int main() {
Foo f;
auto callOp = f.getCallOperator();
}
I want to create a member function in CRTP base class with a return type depending on signature of the operator()
in the derived class. However decltype(&Der::operator())
fails to compile; The operator()
member function in Foo
is not visible. I assume that this is because the base class template is instantiated before Foo
is fully defined.
Surprisingly, if I place auto
for the return type it compiles. I assumed that auto
would make the compiler deduce the return type from the function body and fail - because the body uses the not fully defined Foo
type.
This behavior is the same for both MSVC 2015.3 and Clang 3.8
Why did the code start to work with auto
? Does auto
type deduction somehow "delay" the instantiation? Or use a different context than a hand-written return type expression?
With auto type deduction enabled, you no longer need to specify a type while declaring a variable. Instead, the compiler deduces the type of an auto variable from the type of its initializer expression.
In C++14, you can just use auto as a return type.
Your guess is correct. A deduced return type is not actually deduced until the signature of the function is needed. This means that it will be deduced in the context of the call to getCallOperator
, at which point Foo
is fully defined.
This is specified in 7.1.6.4p12:
Return type deduction for a function template with a placeholder in its declared type occurs when the definition is instantiated even if the function body contains a return statement with a non-type-dependent operand.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With