0

Given the following:

class MyClass
{
   public:
      template <typename T, typename U = T>
      void doSomething(T) {}
   private:
      double parser;
};

template<>
inline void MyClass::doSomething<bool>(bool) {}
template<>
inline void MyClass::doSomething<int, double>(int) {}

int main(int argc, char* argv[])
{
   MyClass foo;
   foo.doSomething<bool>(true);
   foo.doSomething<int, double>(10);
   return 0;
}

This works fine.

However now I want to introduce a class template in order to use a template parameter instead of ParserClass, like so:

template<typename P>
class MyClass
{
   public:
      template <typename T, typename U = T>
      void doSomething(T) {}
   private:
      P parser;
};

template<>
inline void MyClass::doSomething<bool>(bool) {}
template<>
inline void MyClass::doSomething<int, double>(int) {}

int main(int argc, char* argv[])
{
   MyClass<double> foo;
   foo.doSomething<bool>(true);
   foo.doSomething<int, double>(10);
   return 0;
}

Which, however, does no longer work:

test.cpp:12:13: error: 'MyClass' is not a class, namespace, or enumeration
inline void MyClass::doSomething<bool>(bool) {}
            ^
test.cpp:2:7: note: 'MyClass' declared here
class MyClass
      ^
1 error generated.

Is it even possible? How do I combine the member function template parameters and the class template parameters in the above example?

user826955
  • 3,137
  • 2
  • 30
  • 71
  • What "does no longer work" mean? – Sam Varshavchik Jun 29 '21 at 12:42
  • Good point. Might have added the issues. However its probably going to be couple of miles of template error code text. I'll see if I can get something useful into the post. – user826955 Jun 29 '21 at 12:44
  • 2
    any error message is better than no error message. Please also read about [mcve] – 463035818_is_not_an_ai Jun 29 '21 at 12:46
  • I have edited the post. – user826955 Jun 29 '21 at 12:56
  • You can't specialize a member function template without specializing the class template itself. – Evg Jun 29 '21 at 13:12
  • Okay so this would mean I would have to have an implementation for every `P` for the two `doSomething` methods? Thats a bit sad, since I wanted the `doSomething`s to be implemented exactly once (the code would be the same for all `P`). Any other way to achieve the same but without implementing multiple versions of the same `doSomething`? – user826955 Jun 29 '21 at 13:18
  • What about using free (friends) functions instead of member ones? Typically, such problems can be solver by introducing an additional level of indirection. – Evg Jun 30 '21 at 12:38

1 Answers1

1

To specialize a function that is a member of a templated class, you need two template<> declarations. Furthermore, you need to specify the typename for MyClass:

template<> template<>
inline void MyClass<some_type>::doSomething<bool>(bool) { ... }
template<> template<>
inline void MyClass<some_type>::doSomething<int, double>(int) { ... }
Wais Kamal
  • 5,858
  • 2
  • 17
  • 36
  • Okay so this would mean I would have to have an implementation for every `P` for the two `doSomething` methods? Thats a bit sad, since I wanted the `doSomething`s to be implemented exactly once (the code would be the same for all `P`). Any other way to achieve the same but without implementing multiple versions of the same `doSomething`? – user826955 Jun 29 '21 at 13:18
  • You [cannot](https://stackoverflow.com/a/5513109/6649786) specialize a member function without specializing its parent class. – Wais Kamal Jun 29 '21 at 13:43
  • Ok so how could I solve it? I will have around 30 `T`/`U` specializations, which will be the same for all `P`. So I need a way to plug a generic `P` into `MyClass`. – user826955 Jun 29 '21 at 13:58
  • The answer I've posted a link to suggests a solution. The other two answers below it also demonstrate some hacks to help you get around this. – Wais Kamal Jul 01 '21 at 07:49