Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implicit instantiation of function templates when taking their address

Note: I've already looked here and I don't think the answer is right.

What are the rules governing the implicit instantiation of functions when taking their address? 14.7.1/9 of n3242 says this:

An implementation shall not implicitly instantiate a function template, a member template, a non-virtual member function, a member class, or a static data member of a class template that does not require instantiation.

Now, it's certainly not required to have a function definition in order to take its address. We can take the address of forward-declared functions and have them defined in a different translation unit.

That being the case, I don't know when it would be required. Yet, compilers seem to have their own idea. Testing on GCC and VC, here are a few examples:

template <typename T> void CallBanana() { T::Banana(); }
template <typename T> void CallUnimpl();

template <typename T>
struct S {
    static void CallBanana() { T::Banana(); }
    static void CallOrange() { T::Orange(); }
    static void CallUnimpl();
};

struct B { static void Banana() {} };

int main() {
    (void)(&CallBanana<void>); // 1
    (void)(&CallUnimpl<void>); // 2
    (void)(&S<void>::CallBanana); // 3
    (void)(&S<void>::CallOrange); // 4
    (void)(&S<void>::CallUnimpl); // 5
    (void)(&S<B>::CallBanana); // 6
}

These should be commented-in one at a time to see the effects.

GCC 4.7 tested here will complain about 1, 3, and 4. So it is instantiating all definitions if they exist.

VC 2010 (no online test, sorry) instantiates 3 and 4, yet doesn't instantiate 1.

Clang 3.0 tested here has the same behaviour as VC 2010.

No compiler complains about 2 or 5, which I would expect. I would expect it to fail to link if I actually used those pointers though.

On all compilers, 6 compiles. I expect this, but it is intended to show that the whole class template isn't instantiated (as claimed in the answer to that other question) just because I take the address of a single function. If the whole template was instantiated, then S::CallOrange shouldn't compile, because B doesn't contain an Orange function.

So I'm wondering if anyone has a definitive answer as to what the correct behaviour should be. The standard seems to claim that no functions should be instantiated, yet three popular compilers instantiate in some cases, but differ from each other too.

like image 341
Fuz Avatar asked Apr 24 '13 14:04

Fuz


People also ask

How do you instantiate a template in a function?

To instantiate a template function explicitly, follow the template keyword by a declaration (not definition) for the function, with the function identifier followed by the template arguments. template float twice<float>(float original); Template arguments may be omitted when the compiler can infer them.

What is implicit instantiation?

Implicit instantiation means that the compiler automatically generates the concrete function or class for the provided template arguments. In general, the compiler also deduces the template arguments from the function's arguments. In C++17, the compiler can also deduce the template arguments for class templates.

Is it necessary to instantiate a template?

In order for any code to appear, a template must be instantiated: the template arguments must be provided so that the compiler can generate an actual class (or function, from a function template).

What happens when a function is defined as a template?

Function templates are special functions that can operate with generic types. This allows us to create a function template whose functionality can be adapted to more than one type or class without repeating the entire code for each type. In C++ this can be achieved using template parameters.


1 Answers

A definition of a function required if you take its address (within an evaluated context).

Of course the definition can be given in a separate translation unit, but that doesn't change the fact that a definition is needed.

If only one member function is needed, that does not imply that other member functions are instantiated as well.

If the function template is undefined, it cannot be implicitly instantiated. It must then be explicitly instantiated in another translation unit. Relying on an implicit instantiation in another translation unit is disallowed (but no diagnostic is required).

like image 159
Johannes Schaub - litb Avatar answered Sep 28 '22 11:09

Johannes Schaub - litb