Pergunta

I'm trying to write a template function, but I have trouble specializing it for vector<> and another class at the same time. Here is the code I'm using :

// template definition
template< class T >
void f( const T& value) 
{
    cout << "DEFAULT" << endl;
}

// specialization for MyClass
template< class T >
void f<>  ( const MyClass & value )
{
    cout << "MyClass" << endl;
}

// specialization for vector
template< class T >
void f<>( const std::vector<T> & v )
{
    cout << "vector" << endl;
}

MyClass and MyClass2 are defined as:

class MyClass{
virtual void a() = 0;
};

class MyClass2 : public MyClass{
    void a(){}
};

Finally, the main function:

int main(int nArgs, char *vArgs[]){

    MyClass2 e;
    f<MyClass>(e);

}

Here is the error I get when I try compiling it using Visual Studio 2010:

c:\program files (x86)\microsoft visual studio 10.0\vc\include\vector(869): error C2259: 'MyClass' : cannot instantiate abstract class

This seems to be very specific to this particular situation: As soon as I remove the const modifiers, I change the vector into a list or I make MyClass concrete, everything works. But for my problem I need for this particular situation to work.

Is anybody having the same error as me, and more importantly does anybody know a fix/workaround for this?

Foi útil?

Solução

I believe this:

// specialization for vector
template< class T >
void f<>( const std::vector<T> & v )
{
    cout << "vector" << endl;
}

is not possible (even if your syntax were corrected, as Anton did in his answer), because it is not a full specialization of f (there are unbound type parameters). Partial function specialization is not allowed under the C++ standard.

There are a few other questions on Stack Overflow involving similar code with similar issues. This one (and the winning answer) seems to be quite relevant: Why function template cannot be partially specialized?

You can peruse the C++ standards for yourself, if you were feeling particularly masochistic. You might start from section 14.7.3 ("Explicit specialization") at page 368 of this document: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf (which is a semi-recent draft, but not the most up to date. It is free, however.)

Outras dicas

As other answers have indicated:

  • your syntax for specialization is wrong
  • you cannot partially specialize a template function

...does anybody know a fix/workaround for this?

Since you are using the template argument in the argument list, you can use overloaded functions.

template <class T>
void f(const T& value)
{
    std::cout << "DEFAULT" << std::endl;
}

void f(const MyClass& value)
{
    std::cout << "MyClass" << std::endl;
}

template <class T>
void f(const std::vector<T>& v) // this is an overload, not a specialization
{
    std::cout << "vector" << std::endl;
}

int main()
{
    f(1);
    MyClass2 e;
    f(e);
    f(std::vector<int>());
}

You have mistakes in specialization syntax.

Probably, it should look like this:

// MyClass
class MyClass{
virtual void a() = 0;
};

class MyClass2 : public MyClass{
    void a(){}
};

// template definition
template< class T >
void f(const T& value)
{
    cout << "DEFAULT" << endl;
};

// specialization for MyClass
template<>
void f(const MyClass & value)
{
    cout << "MyClass" << endl;
};

// specialization for vector of MyClass
template<>
void f(const std::vector<MyClass> & v)
{
    cout << "vector" << endl;
}

int main()
{
    // Using template for any type
    f(2);

    // Using specialization for MyClass
    MyClass2 e;
    f<MyClass>(e);

    // Using specialization for vector<MyClass>
    vector<MyClass> vM;
    f(vM);
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top