Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Specializing single method in a big template class

In C++ if you want to partially specialize a single method in a template class you have to specialize the whole class (as stated for example in Template specialization of a single method from templated class with multiple template parameters)

This however becomes tiresome in bigger template classes with multiple template parameters, when each of them influences a single function. With N parameters you need to specialize the class 2^N times!

However, with the C++11 I think there might a more elegant solution, but I am not sure how to approach it. Perhaps somehow with enable_if? Any ideas?

like image 836
CygnusX1 Avatar asked Jan 17 '14 09:01

CygnusX1


People also ask

When we specialize a function template it is called?

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 meant by class template?

An individual class defines how a group of objects can be constructed, while a class template defines how a group of classes can be generated. Note the distinction between the terms class template and template class: Class template. is a template used to generate template classes.

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 use of template class?

Definition. As per the standard definition, a template class in C++ is a class that allows the programmer to operate with generic data types. This allows the class to be used on many different data types as per the requirements without the need of being re-written for each type.


1 Answers

In addition to the inheritance-based solution proposed by Torsten, you could use std::enable_if and default function template parameters to enable/disable certain specializations of the function.

For example:

template<typename T>
struct comparer
{
    template<typename U = T ,
    typename std::enable_if<std::is_floating_point<U>::value>::type* = nullptr>
    bool operator()( U lhs , U rhs )
    {
        return /* floating-point precision aware comparison */;
    }

    template<typename U = T ,
    typename std::enable_if<!std::is_floating_point<U>::value>::type* = nullptr>
    bool operator()( U lhs , U rhs )
    {
        return lhs == rhs;
    } 
};

We take advantage of SFINAE to disable/enable the different "specializations" of the function depending on the template parameter. Because SFINAE can only depend on function parameters, not class parameters, we need an optional template parameter for the function, which takes the parameter of the class.

I prefer this solution over the inheritance based because:

  • It requires less typing. Less typing probably leads to less errors.
  • All specializations are written inside the class. This way to write the specializations holds all of the specializations inside the original class , and make the specializations look like function overloads, instead of tricky template based code.

But with compilers which have not implemented optional function template parameters (Like MSVC in VS2012) this solution does not work, and you should use the inheritance-based solution.

EDIT: You could ride over the non-implemented-default-function-template-parameters wrapping the template function with other function which delegates the work:

template<typename T>
struct foo
{
private:
    template<typename U>
    void f()
    {
        ...
    }

public:
    void g()
    {
        f<T>();
    }
};

Of course the compiler can easily inline g() throwing away the wrapping call, so there is no performance hit on this alternative.

like image 101
Manu343726 Avatar answered Sep 21 '22 13:09

Manu343726