jenda
jenda

Reputation: 154

Overloading a std::function parameter in templated method in templated class

I have trouble making a specialized template for a templated method in a class template specialization.

Let's say I have the following code:

#include <functional>

template<typename T>
class myClass {
public:
    T bar() {
        return T();
    }

    template<typename P>
    bool foo(std::function<P(T)> g) {
        g(bar());
        return true;
    }
};

If I wanted to specialize the function bar for myClass<void> I would do it this way:

template<> void myClass<void>::bar() {

}

But when I tried to specialize foo in the same way, i get a compiler error saying error: invalid parameter type ‘void’ and pointing at the original definition of foo.

template<>
template<typename P>
bool myClass<void>::foo(std::function<P(void)> g) {
    bar();
    g();
    return true;
}

Does anybody have any advice, what I'm doing wrong?

Upvotes: 2

Views: 87

Answers (1)

max66
max66

Reputation: 66230

Not exactly specialization... you can use SFINAE (std::enable_if) to activate your version of foo() when T isn't void and activate another version of foo() when T is void.

The following is a full working example

#include <iostream>
#include <functional>

template <typename T>
class myClass
 {
   public:
      T bar()
       { return {}; }

      template <typename P, typename U = T>
      typename std::enable_if<false == std::is_same<U, void>::value,
               bool>::type foo (std::function<P(U)> const & g)
       { g(bar()); return true; }

      template <typename P, typename U = T>
      typename std::enable_if<true == std::is_same<U, void>::value,
               bool>::type foo (std::function<P()> const & g)
       { bar(); g(); return false; }
 };

template<>
void myClass<void>::bar ()
 { }

int main()
 {
   myClass<int>   mci;
   myClass<void>  mcv;

   std::function<long(int)> fli { [](int i){ return long(i); } };
   std::function<short()>   fsv { [](){ return 0; } };

   std::cout << mci.foo(fli) << std::endl; // print 1
   std::cout << mcv.foo(fsv) << std::endl; // print 0
 }

Upvotes: 3

Related Questions