Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 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;
}
like image 386
Artyom Avatar asked Nov 02 '09 18:11

Artyom


1 Answers

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.

like image 160
Pavel Minaev Avatar answered Oct 28 '22 18:10

Pavel Minaev