Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C++

Specialized Function Templates

4.27/5 (6 votes)
11 Feb 2016CPOL 8.7K  
You can't partially specialize function templates - or maybe you can?

Introduction

I had always thought that function templates cannot be specialized partially. But now, I've learned that's only partially true. My knowledge was mainly based on an article from C++ guru Herb Sutter published in C/C++ Users Journal in july 2001. There is also a plethora of questions referring to this subject on stackoverflow.

Background

A typical work-around is to place a class template inside the function that can be specialized partially with no hassle:

C++
template < typename T >
void foo(T&& v) 
{
    helper< T >()(v);
}

Or you make it static:

C++
template < typename T >
void foo(T&& v) 
{
    //    static functions cannot overload 
    //    the function call operator
    helper< T >::foo(v);
}

Surprise

But there were always nagging doubts about this rule. So I wrote the following code recently:

C++
template < typename T >
T foo(std::initializer_list<T> il) 
{
    T result;
    std::for_each(il.begin(), il.end(), [&result](T const& v){
        //    ...
     });
    return result;
}

Then, I added a partial specialized function template:

C++
template < typename T >
T foo(std::initializer_list < std::pair < std::size_t, T > > il) 
{
    T result;
    typedef std::pair< std::size_t, T > value_type;
    std::for_each(il.begin(), il.end(), [&result](value_type const& v){
        // ...
    });
    return result;
}

Surprisingly, this worked as expected using gcc 5.x. But things get worse using MSVC 2015. The Microsoft compiler can't do this trick and used std::initializer_list < std::pair< std::size_t, std::pair < std::size_t, T > > > as argument in the initializer list when T = std::pair < std::size_t, T >. But I'm not sure to blame MSVC here, because it does what the C++ standard requires. But the behaviour of gcc 5.x is definitely much nicer.

History

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)