Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function template overloading vs Explicit specialization

Tags:

c++

templates

stl

I set up two template functions which get sums for different STL containers: one is for list and vector, the other is for the map.

Please see the commented line (1) and (2) of the second template function definition. The commented-out code (=2) also works fine, so I do not know which one is more recommended syntax.

Also, how does each method called (Am I aptly guessed in my comment)? To say (1) is a function template overloading seems not enough because it lacks typename argument after the keyword 'template'. That is, It should be like template<typename T> combined with (1) in order for the method to be called as a function template overloading, I guess. Please give me their right name.

template <typename T> // T : container
double Sum(const T &l) // get Container
{
    double sum = 0;
    T::const_iterator i;
    for (i = l.begin(); i != l.end(); ++i) { sum += *i; }
    return sum;
}

template <> // get container
double Sum(const map<string, double> &m) // (1) function template overloading
// double Sum<map<string, double> >(const map<string, double> &m) // (2) explicit specialization
{
    double sum = 0;
    map<string, double>::const_iterator i; // obtain Iterator from Container
    for (i = m.begin(); i != m.end(); i++) { sum += i->second; } // sum. ('first' is index, 'second' is data)
    return sum;
}
like image 567
RyanC Avatar asked Oct 31 '25 07:10

RyanC


2 Answers

Both are explicit specialization syntax

  • template <> double Sum(const map<string, double> &m);

  • template <> double Sum<map<string, double> >(const map<string, double> &m)

The first one let compiler deduce the parameter, whereas the second, you are explicit.

The second is required when compiler cannot deduced all template parameters as for

template <typename T> std::string getNameType();

template <> std::string getNameType<int>() { return "int"; }

or to disambiguate which template function to specialize

template <typename T> void foo(T);

template <typename T> void foo(T*); // overload, not specialization

//template <> void foo(int*); // Error: do you mean T = int for foo(T*) or T = int* for foo(T)

template <> void foo<int*>(int*); // specialize foo(T)
template <> void foo<int>(int*);  // specialize foo(T*)

It is generally better to use overload instead of specialization for function, so for your example:

template <typename Key>
double Sum(const std::map<Key, double> &m)
{
    double sum = 0;
    for (const auto& p : m) { sum += p.second; }        return sum;
}
like image 199
Jarod42 Avatar answered Nov 01 '25 20:11

Jarod42


I didn't completely understand your question, as your code seems to be OK, but I'll make an attempt to answer. Function overloading is an approach when you manually write several functions with the same name but different argument types. For example:

double Sum(const std::vector<double>& l) {
    //...
}

double Sum(const std::list<double>& l) {
    //...
}

double Sum(const std::deque<double>& l) {
    //...
}

In your example you wrote a function template:

template <typename T>
double Sum(const T &l) //...

and a template specialization:

template <>
double Sum(const map<string, double> &m) //...

Which is better? It depends on your situation. See, with function overloading you should write the code by yourself, while in case of templates the compiler will do it for you!

For example, your general-case template will work for vector, list, queue, deque and any other compatible container which even may be nonexistent for the moment of template creation. Compiler generates the code only for those types which are used to instantiate the template. If you try to instantiate it with incompatible type, you'll get a compilation error. And only if you instantiate it with map<string, double> (which is invalid for the general case template), compilation will succeed as the specialization will be selected for code generation.

As @RichardHodges mentioned, specialization might be an overkill for your case; non-template overloading should be enough.

like image 32
Sergey Avatar answered Nov 01 '25 21:11

Sergey