6

In answering this question, I came across this difference in behaviour with respect to template instantiation.

Initially there is a function template

template <typename T> void my_callback(void* data) { … }

Now something requires the address of this - specifically a void*, so the obvious approach is

bar(reinterpret_cast<void*>(&my_callback<int>));

However, with compiler versions pre gcc 4.5, this fails with a not-enough context... error. Fine - so the fix is to "cast" first - which forces instantiation, i.e:

void (*callback)(void*) = my_callback<int>;
bar(reinterpret_cast<void*>(callback));

This works fine.

Now the second scenario, rather than being a free function, it's a static member of a class template, i.e.

template <typename T>
struct foo
{
  static void my_callback(void* data) {
    T& x = *static_cast<T*>(data);
    std:: cout << "Call[T] with " << x << std::endl;
  }
};

Now, the original reinterpret_cast works fine.

bar(reinterpret_cast<void*>(&foo<int>::my_callback));

So my question is - why this apparent difference in behaviour?

Community
  • 1
  • 1
Nim
  • 33,299
  • 2
  • 62
  • 101

1 Answers1

2

From n3290, 14.7.1 Implicit instantiation [temp.inst]

2 Unless a function template specialization has been explicitly instantiated or explicitly specialized, the function template specialization is implicitly instantiated when the specialization is referenced in a context that requires a function definition to exist.

There are similar rules in paragraph 1 for class template specializations. Notice that the Standard speaks in terms of specialization because a specialization is implicitly declared when a template is used an no user-provided specialization is here, at least for function templates (paragraph 8).

Combined with paragraph 10,

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

I think the rule of thumb is: as soon as an object/class member/function is needed or to make the program otherwise work (speaking informally), the template is implicitly instantiated but no sooner. This include taking the address of a function.

As to the question you linked, some uses of reinterpret_cast may make the program non-conformant, by which time it's irrelevant to mention instantiations -- I invite you to see my answer there</shameless>.

Community
  • 1
  • 1
Luc Danton
  • 34,649
  • 6
  • 70
  • 114
  • so basically, to take the address of a member (even static), the type has to be instantiated - so the compiler will, but not for a free function because it doesn't need to... thx. – Nim Jul 18 '11 at 16:13
  • 1
    @Nim: Obtaining the address of a function requires the function definition (from which the linker will obtain the address), so obtaining the address of a template function should imply the instantiation of that particular specialization of the function. – David Rodríguez - dribeas Jul 18 '11 at 17:11
  • @David, yes, which is why I asked, how come the reinterpret_cast of the address of doesn't work for a function template, tbh, I've not tried the indirect version as in Luc's answer yet. – Nim Jul 18 '11 at 18:56
  • 1
    @Nim It doesn't work because it doesn't have to. In the words of the n3290 draft for C++0x, casting from a function pointer type to an object pointer type is 'conditionally-supported'. C++03 offers even less guarantees I believe. – Luc Danton Jul 18 '11 at 19:09