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:
template < typename T >
void foo(T&& v)
{
helper< T >()(v);
}
Or you make it static
:
template < typename T >
void foo(T&& v)
{
helper< T >::foo(v);
}
Surprise
But there were always nagging doubts about this rule. So I wrote the following code recently:
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:
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