I just came across a problem with MSVC (Version 12 Update 5):
Explicitly instantiating a template function fails, if that function has an overload which is disabled through SFINAE. However, calling that function (thereby implicity instantiating it) works.
Sample code:
#include <type_traits>
template <typename T>
std::enable_if_t< std::is_integral<T>::value, // test is true for T=int
void> foo( T& ) {}
template <typename T>
std::enable_if_t< std::is_pointer<T>::value, // test is false for T=int
void> foo( T& ) {}
void bar( )
{
int i;
foo( i ); // calls foo( int& ) (obviously), compiles fine
}
template void foo( int& ); // explicit instantiation, throws compiler error
error C2794: 'type' : is not a member of any direct or indirect base class of 'std::enable_if<false,void>'
The following allows to instantiate the function, making sure it compiles and should (by my understanding) also put it into the .obj-file:
namespace {
template <typename T>
void helper( T& A )
{
foo( A );
}
template void helper( int& );
}
The trick here is, that helper(..)
is neither overloadad, nor disabled for any type. Sorting out the disabled overloads is delayed to the 'call' to foo(..)
within helper(..)
, which MSVC succeeds to resolve.
EDIT: As we have seen that other compilers understand my original code, as well as newer versions of MSVC (thanks Niall), I assume it is a bug of my version of MSVC, and consider that part question sufficiently thought over.