Using valid STATIC member function of class that can't be installed
I have following piece of code:
It compiles without problems under gcc-3.4, gcc-4.3, intel compiler, but fails under MSVC9.
MSVC tells "use of undefined type c_traits<C>
, while compiling class template member function void foo<C>::go(void)
with C=short.
The point it the compiler tries to install unused member function of unused class, because this class is just not used at all.
I can work-around开发者_JS百科 the issue by specializing entire class foo instead of specializing its member function. But the point it that specializing entire class is little bit problematic for me for different reasons.
The big question: what is right?
- Is my code wrong and gcc and intel compiler just ignore the issue because they do not install foo fully, or
- The code is correct and this is bug of MSVC9 (VC 2008) that it tries to install unused member functions?
The code:
class base_foo {
public:
virtual void go() {};
virtual ~base_foo() {}
};
template<typename C>
struct c_traits;
template<>
struct c_traits<int> {
typedef unsigned int_type;
};
template<typename C>
class foo : public base_foo {
public:
static base_foo *create()
{
return new foo<C>();
}
virtual void go()
{
typedef typename c_traits<C>::int_type int_type;
int_type i;
i=1;
}
};
template<>
base_foo *foo<short>::create()
{
return new base_foo();
}
int main()
{
base_foo *a;
a=foo<short>::create(); delete a;
a=foo<int>::create(); delete a;
}
Both compilers are right here; the behavior for your case is unspecified. ISO C++ 14.7.1[temp.inst]/9:
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. It is unspecified whether or not an implementation implicitly instantiates a virtual member function of a class template if the virtual member function would not otherwise be instantiated.
The reasoning for this is fairly simple: a virtual function requires a vtable entry, and with virtual dispatch, it may be tricky for the compiler to determine whether a given virtual function is actually called or not. Therefore, ISO C++ permits the compilers to do such advanced analysis for the sake of generating smaller code, but does not require it of them - so, as a C++ programmer, you should always assume that all virtual functions will always be instantiated.
The removal of unused functions will occur at linking not at compilation where you are having your error. MSVC may not know who amongst all the compilation units being compiled who will ultimately call that method. It can't know until compilation is complete and until linking occurs. Naturally different compilers may be smarter about this, but I suspect this may be what is happening.
I suspect your specific compiler errors sounds like it is caused by you having only forward declared
template<typename C>
struct c_traits;
you have not fully specified the class. Did you try something as simple as:
template<typename C>
struct c_traits
{
// some default/dummy int type
};
I suspect this would at least stop the compiler from complaining.
EDIT
this is generally wrong for class templates. Member functions of class templates aren't supposed to be compiled (and any errors in their bodies aren't supposed to be triggered) unless they're instantiated
The template is instantiated in this case in the form of:
foo<short>
The compiler will treat this as any other class who's methods have potential for external linkage. I haven't heard any special language rule that says that external linkage doesn't apply to templates...?
精彩评论