Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does casting to a pointer to a template instantiate that template?

static_cast<the_template<int>*>(0) - does this instantiate the_template with type int?

The reason for asking is the following code, which will error at linking time with an undefined reference to check_error<char>(void*, long) with Clang and GCC 4.4.5, indicating that it does not instantiate the template. MSVC and GCC 4.5.1 however compile and link just fine, leading to the believe that it does instantiate the template. However, if you leave out the cast, MSVC and GCC (both 4.4.5 and 4.5.1) will error on check_error<char> only (the wanted behaviour), while Clang will error on both calls. Normally I believe Clang when it comes to conforming stuff, but I wonder:

Which compiler is correct and what does the standard say about it?


#include <type_traits>

template<class T>
void check_error(void*, long);

template<class T>
struct foo{
  template<class U>
  friend typename std::enable_if<
    std::is_same<T,U>::value
  >::type check_error(foo<T>*, int){}
};

template struct foo<int>;

int main()
{
  check_error<int>(static_cast<foo<int>*>(0), 0);
  check_error<char>(static_cast<foo<char>*>(0), 0);
}
like image 627
Xeo Avatar asked Dec 04 '11 22:12

Xeo


People also ask

How do I force a template instantiation?

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 instantiation of a template?

The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation to handle a specific set of template arguments is called a specialization.

Can template type be a pointer?

A template has only one type, but a specialization is needed for pointer, reference, pointer to member, or function pointer types. The specialization itself is still a template on the type pointed to or referenced.

How is a template class different from a template function?

For normal code, you would use a class template when you want to create a class that is parameterised by a type, and a function template when you want to create a function that can operate on many different types.


2 Answers

It is not the cast that instantiates the class template specialization, but the function call, because the argument triggers ADL . The instantiation is done because the completeness of it may affect the semantics of the program.

That clang does not follow the spec here is known and a PR was sent by me some time ago. See http://llvm.org/bugs/show_bug.cgi?id=9440

like image 53
Johannes Schaub - litb Avatar answered Oct 07 '22 19:10

Johannes Schaub - litb


n3242 §14.7.1/1

Unless a class template specialization has been explicitly instantiated (14.7.2) or explicitly specialized (14.7.3), the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type or when the completeness of the class type affects the semantics of the program. The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions or default arguments, of the class member functions, member classes, static data members and member templates; and it causes the implicit instantiation of the definitions of member anonymous unions. Unless a member of a class template or a member template has been explicitly instantiated or explicitly specialized, the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist; in particular, the initialization (and any associated side-effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist.

It seems to me that static_cast would require the instantiation of the declarations, but not of the definitions (as you are just dealing with pointers).

n3242 §14.6.5/1

Friend classes or functions can be declared within a class template. When a template is instantiated, the names of its friends are treated as if the specialization had been explicitly declared at its point of instantiation.

I think that it should link, but maybe someone else can interpret better than I can.

like image 36
David Avatar answered Oct 07 '22 20:10

David