I would like to define a template function but disallow instantiation with a particular type. Note that in general all types are allowed and the generic template works, I just w
If you don't want to rely on static_assert
or make the code portable pre-C++0x, use this:
template<class T>
void func(){
typedef char ERROR_in_the_matrix[std::is_same<T,double>::value? -1 : 1];
}
int main(){
func<int>(); // no error
func<double>(); // error: negative subscript
}
You could use a functor instead of a function:
template<typename T>
struct convert {
T operator()(char const * in) const { return T(); }
};
template<> struct convert<double>;
int main()
{
char const * str = "1234";
int a = convert<int>()( str );
double b = convert<double>()( str ); // error in this line
return 0;
}
This will give you an error at the point of instantiation.
By adding helper function you will get the wanted behaviour:
template<typename T>
struct convert_helper {
T operator()(char const * in) const { return T(); }
};
template<> struct convert_helper<double>;
template<typename T>
T convert( char const * in ) { return convert_helper<T>()( in ); }
int main()
{
char const * str = "1234";
int a = convert<int>( str );
double b = convert<double>( str );
return 0;
}
Consider Boost disable_if
and Boost TypeTraits
Take a look at How can I write a function template for all types with a particular type trait?
This is an example:
#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>
template<typename T>
T convert( char const * in,
typename boost::disable_if<boost::is_floating_point<T>, T>::type* = 0 )
{ return T(); }
int main()
{
char const * str = "1234";
int a = convert<int>( str );
double b = convert<double>( str );
return 0;
}
This is the compilation error for the string
double b = convert<double>( str );
1>.\simple_no_stlport.cpp(14) : error C2770: invalid explicit template argument(s) for 'T convert(const char *,boost::disable_if,T>::type *)' 1> .\simple_no_stlport.cpp(5) : see declaration of 'convert'
I would use a static assert within your function call to create the proper failure during function instantiation:
template<typename T>
class is_double{ static const int value = false; }
template<>
class is_double<double>{ static const int value = true; }
template<typename T>
T convert( const char *argument ){
BOOST_STATIC_ASSERT( !is_double<T>::value );
//rest of code
}
And that should work within a function.