views:

70

answers:

2

I have the following (minimized) code, which worked in VC2005, but no longer works in 2010.

template <typename TDataType>
class TSpecWrapper
  { 
  public:
    typedef typename TDataType::parent_type index_type;


  public:

    template <bool THasTriangles>
    void Spec(index_type& io_index)
      { std::cout << "False version" << std::endl; }

    template <>
    void Spec<true>(index_type& io_index)
      { std::cout << "True version" << std::endl; }
  };

It seems that when "index_type" is a dependent type, I always get a C2770: invalid explicit template argument(s) error on the specialization. Note that this code is actually enough to generate the error - an empty main is sufficient to compile it, the template need not even be instantiated.

It works fine if index_type is not a dependent type. Any ideas why this is so in VC2010, if this is actually standard behaviour or a bug, and if I can work around it?

+3  A: 

This is according to C++ Standard 14.7.3/18:

In an explicit specialization declaration for a member of a class template or a member template that appears in namespace scope, the member template and some of its enclosing class templates may remain unspecialized, except that the declaration shall not explicitly specialize a class member template if its enclosing class templates are not explicitly specialized as well. <...>

It is not allowed to specialize Spec without specializing TDataType.

Kirill V. Lyadvinsky
But it works fine if index_type is not a dependent type (e.g. int)...
MadKeithV
Actually, reading through the responses, it seems that VS2005 was very liberal, and 2010 a little less liberal, but still more liberal than the standard allows. So I guess in a way this question is a duplicate of http://stackoverflow.com/questions/3052579/explicit-specialization-in-non-namespace-scope (at least the answer to that question also covers mine)
MadKeithV
+4  A: 

Workaround

template <bool v> struct Bool2Type { static const bool value = v; }; 

template <typename TDataType> 
class TSpecWrapper 
{  
public: 
    typedef typename TDataType::parent_type index_type; 


public: 
    template <bool THasTriangles> 
    void Spec(index_type& io_index) 
    { 
        return SpecHelp(io_index, Bool2Type<THasTriangles>());
    } 

private:
    void SpecHelp(index_type& io_index, Bool2Type<false>) 
    { std::cout << "False version" << std::endl; } 

    void SpecHelp(index_type& io_index, Bool2Type<true>) 
    { std::cout << "True version" << std::endl; } 

}; 
Alexey Malistov
Thanks for that - this helps me work around the issue!
MadKeithV
Thats a *VERY* useful workaround!
Vargas