7

I want to specialize following member function:

class foo {
    template<typename T>
    T get() const;
};

To other class bar that depends on templates as well.

For example, I would like bar to be std::pair with some template parameters, something like that:

template<>
std::pair<T1,T2> foo::get() const
{
    T1 x=...;
    T2 y=...;
    return std::pair<T1,T2>(x,y);
}

Where T1 and T2 are templates as well. How can this be done? As far as I know it should be possible.

So now I can call:

some_foo.get<std::pair<int,double> >();

The full/final answer:

template<typename T> struct traits;
class foo {
    template<typename T>
    T get() const
    {
       return traits<T>::get(*this); 
    }
};

template<typename T>
struct traits {
    static T get(foo &f)
    {
        return f.get<T>();
    }
};

template<typename T1,typename T2>
struct traits<std::pair<T1,T2> > {
        static std::pair<T1,T2> get(foo &f)
        {
                T1 x=...;
                T2 y=...;
                return std::make_pair(x,y);
        }
};
Artyom
  • 31,019
  • 21
  • 127
  • 215
  • It's not clear what you mean. Do you want a specialization that applies whenever T1 and T2 are templates? Or when they are some specific template? Or when they are templates, and their parameter is some specific type(s)? – jalf Aug 23 '09 at 12:41
  • I mean, that I want to specialize my function for other specific type (like std::pair) that need some template parameters as well. – Artyom Aug 23 '09 at 12:47
  • Please check this: http://stackoverflow.com/questions/947943/template-specialisation-where-templated-type-is-also-a-template – Vijay Mathew Aug 23 '09 at 12:52

2 Answers2

8

You can't partially specialize function templates, sorry but those are the rules. You can do something like:

class foo {
   ...
};


template<typename T>
struct getter {
  static T get(const foo& some_foo);
};

template<typename T1, typename T2>
struct getter< std::pair<T1, T2> > {
static std::pair<T1, T2> get(const foo& some_foo) {
    T1 t1 = ...;
    T2 t2 = ...;
    return std::make_pair(t1, t2);
};

and then call it like

getter<std::pair<int, double> >::get(some_foo);

though. You may have to do some messing around with friendship or visibility if get really needed to be a member function.

To elaborate on sbi's suggestion:

class foo {
   ...
   template<typename T>
   T get() const;
};

template<typename T>
T foo::get() const
{
  return getter<T>::get(*this);
  /*            ^-- specialization happens here */
}

And now you're back to being able to say

std::pair<int,double> p = some_foo.get<std::pair<int, double> >();
Logan Capaldo
  • 39,555
  • 5
  • 63
  • 78
  • 1
    You could. however, make `getter` a (prossibly `private`) member of the class and have it called through a normal member function template. That way, users of your class don't have to care about this mechanism. – sbi Aug 23 '09 at 19:21
1

You need to overload your member function for pair, like in

template <T, V> std::pair<T, V> foo::get()

In the general case you will need to be able to disambiguate between the various overloads. In the case disambiguation is easy because pair is templated on 2 types while the original member was templated on T only.

If instead you needed a specialization for, e.g., std::vector, that is for a container with a single parameter template, you have to be careful since given it can be confusing for the compiler to understand if you wish to instantiate the template specialization where the template T is std::vector or the specialization for the overload,

template <T> std::<vector <T> foo::get() const 

Your proposed syntax cannot work since you are completely specializing the member function,

template <>,

but you are leaving out two unspecified types, T1 and T2.

Francesco
  • 3,200
  • 1
  • 34
  • 46
  • This does not work: "prototype for `std::pair<_T1, _T2> foo::get()` does not match any in class `foo` ; candidate is: template T foo::get()" – Artyom Aug 23 '09 at 13:49
  • you would have to declare in class foo `template std::pair get() const;` and then call it something like: `std::pair p_int = f.get(); ` – Francesco Aug 23 '09 at 14:48