user1518812
user1518812

Reputation: 31

Mix explicit specialization and unspecialized templates

I am a template newbie. I had a question, is there a way to specialize a class member function with unspecialized (or generic) types as parameters. That is can the U1 and U2 in the following program be a say, boost::shared_ptr of type U1 while the T1 and T2 are regular types.

#include <iostream>

template <typename T1, typename T2>
class X {
    public:
    template <typename U1, typename U2>
    void get_as(U1& source, U2& dest);
};

class Y {
};

template<> template<>
void
X<int, int>::get_as<double, double>(double& source, double& dest) {
    std::cout << "SOURCE IS " << source << std::endl;
    std::cout << "DESTINATION IS " << dest << std::endl;
}

template<> template<>
void 
X<int, int>::get_as<shared_ptr, shared_ptr>(shared_ptr<Y>& source, shared_ptr<Y>& dest) {
//some logic
}


int main()
{
    double d1 = 1.0;
    double d2 = 1.1;
    X<int, int> x;
    x.get_as(d1, d2);
    shared_ptr<Y> p1(new Y());
    shared_ptr<Y> p2(new Y());
    x.get_as(p1, p2); //Would this work?

    return 0;
}

I tried reading on it but could clearly understand that if it could or could not be done.

Upvotes: 3

Views: 207

Answers (1)

Cogito Learning
Cogito Learning

Reputation: 23

The code in your example will not compile because the shared_ptr that appears in your template arguments is not a complete type. To make it work, you can modify the function like this:

template<> template<>
void
X<int, int>::get_as<shared_ptr<Y>, shared_ptr<Y> >(shared_ptr<Y>& source, shared_ptr<Y>& dest) {
//some logic
}

But this is maybe not the generality that you are looking for. Unfortunately you can't do the following

template<> template<typename T>
void
X<int, int>::get_as<shared_ptr<T>, shared_ptr<T> >(shared_ptr<T>& source, shared_ptr<T>& dest) {
//some logic
}

This would be a partial template specialization of a member function of a templated class. C++ forbids this kind of thing. However, when learning all about templates and template specialization, one frequently forgets that there is the good old function overloading still available. The following code will work just as you expect it

class Y {
};

class Z {
};

template <typename T1, typename T2>
class X {
    public:
    template <typename U1, typename U2>
    void get_as(U1& source, U2& dest);

    template <typename U>
    void get_as(shared_ptr<U> source, shared_ptr<U> dest);

    void get_as(shared_ptr<Y> source, shared_ptr<Y> dest);
};



template<> template<>
void
X<int, int>::get_as<double, double>(double& source, double& dest) {
    std::cout << "SOURCE IS " << source << std::endl;
    std::cout << "DESTINATION IS " << dest << std::endl;
}

template <typename T1, typename T2>
template <typename U>
void X<T1, T2>::get_as(shared_ptr<U> source, shared_ptr<U> dest)
{
  std::cout << "Overloaded member" << std::endl;
}

template <typename T1, typename T2>
void X<T1, T2>::get_as(shared_ptr<Y> source, shared_ptr<Y> dest)
{
  std::cout << "Special overloaded member" << std::endl;
}

int main()
{
    double d1 = 1.0;
    double d2 = 1.1;
    X<int, int> x;
    x.get_as(d1, d2);
    shared_ptr<Y> p1(new Y());
    shared_ptr<Y> p2(new Y());
    x.get_as(p1, p2); //Would this work?

    shared_ptr<Z> p3(new Z());
    shared_ptr<Z> p4(new Z());
    x.get_as(p3, p4); //Would this work?

    return 0;
}

The output is

SOURCE IS 1
DESTINATION IS 1.1
Special overloaded member
Overloaded member

Upvotes: 1

Related Questions