2

There is this code:

#include <iostream>
#include <string>
#include <typeinfo>

// template class
template <class U, class X, class T>
class Klasa{
public:   
    template <class Z>
    void Method(){
    }
};

// partial class specialization
template <class U>
class Klasa<U, int, U>
{
public: 
    // template method
    template <class Z>
    void Method(){
    }
};

// error occurs for that!
template <class U>
template <>
void Klasa<U, int, U>::Method<int>(){
}

int main() 
{ 
    Klasa<float, int, float> object;
    object.Method<float>();
    return 0;
} 

Compilation error:

error: invalid explicit specialization before ‘>’ token
error: enclosing class templates are not explicitly specialized
error: template-id ‘Method<int>’ for ‘void Klasa<U, int, U>::Method()’ does not match any template declaration

I try to do specialization for method

void Klasa<U, int, U>::Method<int>

, however compiler doesn't accept it. How to write specialization for this method?

scdmb
  • 15,091
  • 21
  • 85
  • 128
  • 2
    The error is clear -- you _can't_ do this while only partially specializing the class. – ildjarn Feb 10 '12 at 18:23
  • 1
    Read this too: http://stackoverflow.com/questions/9219157/why-cant-i-specialize-the-nested-template-member-without-specializing-enclosing and this http://stackoverflow.com/questions/2537716/why-is-partial-specialziation-of-a-nested-class-template-allowed-while-complete – Mr.Anubis Feb 10 '12 at 18:24

2 Answers2

1

I understand, for each partial specialization of Klasa< U, X, T > you want to "specialize" (overload, really, there is no function (EDIT: partial) specialization (EDIT: which you, effectively, trying to achieve)) Method() just once for type X. Here is code (ideone link), see if that's what you need. Also, you might really want to consider some trait classes that would help to eliminate repeats (I assume Method() is the same for all generic Klasa< U, X, T>, and you need to provide additional implementations for specific specializations for type X). EDIT: Maybe, I should mention, that you'll get compilation error trying to use Method< int >(). Assumption is that user of the class understands that he needs to call Klasa< U, X, T >::Method() to get X "specialization" of Method< Z >().

#include <iostream>

template< class U, class X, class T >
class Klasa
{
  public:
    template< typename Z >
    void Method()
    {
    }
};

template< class U >
class Klasa< U, int, U >
{
  public:
    template< typename Z >
    void Method()
    {
      typedef typename std::enable_if< !std::is_same< int, Z >::value, Z >::type whatever;

      std::cout << "Method< Z >" << std::endl;
    }
   void Method()
    {
      std::cout << "Method< int >" << std::endl;
    }
};

int main()
{
  Klasa< float, int, float > lK;

  lK.Method< float >();
  lK.Method< double >();
  lK.Method();

  return( 0 );
}

Program output:

Method< Z >
Method< Z >
Method< int >
lapk
  • 3,838
  • 1
  • 23
  • 28
  • "*overload, really, there is no function specialization*" There is function template specialization, just not _partial_ function template specialization. – ildjarn Feb 10 '12 at 21:30
  • @ildjarn I guess, the wording is bad. I meant, "no function specialization" in the context. `Klasa::Method< int >` is _partial_ specialization, of course, you are absolutely right. – lapk Feb 10 '12 at 21:55
0

Don't ask me for exact quotes but according to David Vandevoorde this can't be done. The rationale is that this is essentially a partial specialization of a function template and there is no such thing. One reason to disallow this is that it is unclear what should happen with this specialization if there is a further specialization of the class: is the function specialization inherited or is it not inherited?

Obviously, stating that this can't be done isn't really a lot of help. What can be done instead? A simple approach would be to delegate the implementation to an overloaded private implementation which takes e.g. a pointer argument to disambiguate between the various types. I realize that the whole point probably is to avoid the use of an extra argument, even if it is only used internally. Another possible approach could be the use of fully specialized base class: member function templates of this can be explicitly specialized.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380