struct Value {
using a_type = int;
a_type f() { return 1; }
};
template<typename T>
struct Wrapper {
T t;
auto call_f() { return t.f(); }
};
int main() {
Wrapper<Value> w;
Wrapper<int> w2;
w.call_f();
}
This compiles fine on Clang and GCC. Wrapper<int>
gets instantiated even though the return type of Wrapper<int>::call_f()
can not be deduced (there is no int::f()
). It fails only when w2.call_f()
gets called.
Is this part of the C++ standard, and can it be expected to work on all compilers?
Yes, this is part of the C++ standard.
The rules of template instantiation are long and complex, but the short version is that a member function of a template class is only instantiated when needed. If nothing calls it, or tries to take a pointer to it, or explicitly instantiates it (and probably a few other cases that I'm forgetting), then it won't be instantiated and your code is well-formed.
As @dyp points out, it is only the declaration of the member function which is instantiated when the class definition is instantiated ([temp.inst]/1
), but the return type deduction is only carried out when the function definition is instantiated ([dcl.spec.auto]/12
).
This is extremely helpful both for minimising the overhead of templates and being permissive about type requirements. It's this feature which lets you do something like this:
struct Foo {
//no default constructor
Foo(int);
};
std::vector<Foo> foos;
Some std::vector
functions (resize
, for example) require T
to be default-constructible, but as long as you don't call those functions you can still use other features of std::vector
.
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