7

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.

Community
  • 1
  • 1
Fuz
  • 235
  • 2
  • 4
  • I quite disagree, as far as I can see the Standard requires the function to be instantiated when its address is taken and all 6 addresses are taken. If the function cannot be instantiated (1, 3 and 4) then a compilation error will be raised. So I would say that 2, 5 and 6 should be instantiated; and since their address is taken (whether you cast to `void` is irrelevant) their absence should provoke a linker error (unless optimized). – Matthieu M. Apr 24 '13 at 15:06
  • 'as far as I can see' - where? Section and paragraph, please. The casts to void are simply to avoid warnings about expressions being used as statements, not related to what I'm doing. – Fuz Apr 24 '13 at 15:50
  • If I had the section and paragraph, it would be an answer ;) I believe it falls under the odr-used case. – Matthieu M. Apr 24 '13 at 17:42

2 Answers2

6

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).

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • 14p6 for that last point, I think. Regarding your main point, a function definition isn't required to be visible even for it to be *called*, but the standard clearly intends that a call results in instantiating a function template definition; taking a pointer isn't any different. – ecatmur Apr 24 '13 at 16:56
  • 14.7.1/2 says "the function template specialization is implicitly instantiated when the specialization is referenced in a context that requires a function definition to exist". It's a little bit woolly (in my mind), but I guess this can be interpreted that way. If so, is Clang deficient by not instantiating the non-member function templates? I'm less surprised by VC getting it wrong. :) – Fuz Apr 24 '13 at 18:10
  • I've marked this as the accepted answer, though I'd be happier if there was a clearer explanation than 'requires a function definition to exist' to see if VC and Clang's behaviour is sanctioned by the standard. – Fuz Apr 25 '13 at 15:25
0

The instantiation needs to occur, because the expansion of the template might not result in wellformed code.

In fact, the instantiation might not even result in a valid prototype (this failure would qualify as 'not a failure').

(When SFINAE is involved the effective address taken might disregard several earlier candidates in the partial ordering (because Substitution Failure Is Not An Error), before the actual candidate is selected to take the address of.)

sehe
  • 374,641
  • 47
  • 450
  • 633
  • I think this is incorrect. 14.7.1/8 says "If a function template or a member function template specialization is used in a way that involves overload resolution, a declaration of the specialization is implicitly instantiated". Note the *declaration* is instantiated, not the definition. – Fuz Apr 24 '13 at 16:03