Pirx un[blog]ged

Mike is reading four blogs. This is none of them.

Specialized function templates

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 Herb Sutter published in C/C++ Users Journal in july 2001. There is also a plethora of question refering to this subject on stackoverflow.

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

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

Or you make it static:

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

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

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

Than I added a partial specialized function template:

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.


comments powered by Disqus