Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

template specialization of template class

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);
        }
};
like image 279
Artyom Avatar asked Aug 23 '09 12:08

Artyom


People also ask

What is a template specialization?

The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization.

What is template class and template function?

Function templates. Function templates are special functions that can operate with generic types. This allows us to create a function template whose functionality can be adapted to more than one type or class without repeating the entire code for each type. In C++ this can be achieved using template parameters.

What is the difference between class template and template class?

A class template is a template that is used to generate classes whereas a template class is a class that is produced by a template.

What is the difference between generic class template and specialization template?

Key differences between generics and C++ templates: Generics are generic until the types are substituted for them at runtime. Templates are specialized at compile time so they are not still parameterized types at runtime. The common language runtime specifically supports generics in MSIL.


2 Answers

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> >();
like image 157
Logan Capaldo Avatar answered Oct 20 '22 13:10

Logan Capaldo


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.

like image 37
Francesco Avatar answered Oct 20 '22 14:10

Francesco