Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the compiler try to instantiate a template that I don't actually instantiate anywhere?

Updated below.
The following is the entire code I have in my main.cpp:

template<class T>
struct other_traits;

template<class T>
struct some_traits{
    typedef decltype(&T::operator()) Fty;
    typedef typename other_traits<Fty>::type type;
};

int main(){
}

But I get the following errors with Visual Studio 2010 while g++ compiles just fine:

src\main.cpp(9): error C2146: syntax error : missing ';' before identifier 'type'
--src\main.cpp(10) : see reference to class template instantiation 'some_traits<T>' being compiled
src\main.cpp(9): error C2868: 'some_traits<T>::type' : illegal syntax for using-declaration; expected qualified-name

(I like that last one, total wtf.)

Can I take that as a bug in VC10 or is there any good reason for the early instantiation? Or is it a bug with decltype that makes the compiler think that Fty is not a dependent name?


Update: I tried to cheat the compiler in thinking that Fty is a dependent name using a base class to inherit from:

template<class T>
struct other_traits;

template<class R, class C>
struct other_traits<R (C::*)()>{
    typedef R type;
};

template<class Fty>
struct base_traits{
    typedef typename other_traits<Fty>::type type;
};

template<class T>
struct some_traits
    : public base_traits<decltype(&T::operator())>
{};

But the compiler still tries to instantiate / compile everything on the spot, spewing these errors:

src\main.cpp(13): error C2039: 'type' : is not a member of 'other_traits<T>'
          with
          [
              T=
          ]
          src\main.cpp(19) : see reference to class template instantiation 'base_traits<Fty>' being compiled
          with
          [
              Fty=
          ]
          src\main.cpp(19) : see reference to class template instantiation 'some_traits<T>' being compiled
src\main.cpp(13): error C2146: syntax error : missing ';' before identifier 'type'
src\main.cpp(13): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
src\main.cpp(13): error C2602: 'base_traits<Fty>::type' is not a member of a base class of 'base_traits<Fty>'
          with
          [
              Fty=
          ]
          src\main.cpp(13) : see declaration of 'base_traits<Fty>::type'
          with
          [
              Fty=
          ]
src\main.cpp(13): error C2868: 'base_traits<Fty>::type' : illegal syntax for using-declaration; expected qualified-name
          with
          [
              Fty=
          ]

Note that the template parameters are empty. Any ideas?

like image 586
Xeo Avatar asked Jun 07 '11 10:06

Xeo


People also ask

What causes a C++ template function to be instantiated?

When a function template is first called for each type, the compiler creates an instantiation. Each instantiation is a version of the templated function specialized for the type. This instantiation will be called every time the function is used for the type.

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

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.

Are templates instantiated at compile time?

Templates are instantiated in the process of converting each translated translation unit into an instantiation unit. A translation unit is essentially a source file. A translated translation unit (try to say that three times fast) is the output from compilation without templates instantiated.


1 Answers

It seems to be a Bug (if there is not special flag set as mentioned below). Following is an excerpt from Oracle website for C++ templates:

7.2.2

The ISO C++ Standard permits developers to write template classes for which all members may not be legal with a given template argument. As long as the illegal members are not instantiated, the program is still well formed. The ISO C++ Standard Library uses this technique. However, the -template=wholeclass option instantiates all members, and hence cannot be used with such template classes when instantiated with the problematic template arguments.

like image 169
iammilind Avatar answered Oct 15 '22 20:10

iammilind