我有一个带有函数的泛型类,我想在编译时将其限制为浮点类型的实例。如下例所示:
template <typename T>
class ClassName
{
// instance variables, etc..
void some_method()
{
// do stuff, but only for floating point types
}
}
如何让编译器拒绝some_method用于非浮点类型的ClassName?
我一直在看SFINAE,但我根本无法让它工作,所以经过几个小时的失败后,我会请求你的帮助。
谢谢:)
答案 0 :(得分:6)
如果编译器支持c ++ 11
,请使用static_assertvoid some_method()
{
static_assert( std::is_floating_point<T>::value, "Only for floating points" );
// do stuff, but only for floating point types
}
如果尝试为非浮点参数调用此方法,则会出现编译器错误。
对于非浮动点:
static_assert( !std::is_floating_point<T>::value, "and only for non-floating point" );
答案 1 :(得分:6)
您可以使用std::is_floating_point
和std::enable_if
的组合来仅启用浮点类型的函数:
#include <type_traits>
template <typename T>
class ClassName
{
// instance variables, etc..
public:
template<typename T2 = T,
typename = typename std::enable_if< std::is_floating_point<T2>::value >::type>
void some_method()
{
// do stuff, but only for floating point types
}
};
int main()
{
ClassName<double> d; // OK
d.some_method(); // OK
ClassName<int> i; // OK
i.some_method(); // ERROR
}
答案 2 :(得分:3)
这样的事情:
template< typename Tdummy = T, typename = typename std::enable_if< std::is_floating_point< Tdummy >::value >::type >
void some_method()
{
}
编辑精心制作。这将导致以下结果。编译器仅为具有浮点模板参数的some_method()
生成ClassName
。它不会为非浮点类型生成,并且会导致编译时错误。
#include <type_traits>
template <typename T>
class ClassName
{
// instance variables, etc..
template< typename Tdummy = T, typename = typename std::enable_if< std::is_floating_point< Tdummy >::value >::type >
void some_method()
{
// do stuff, but only for floating point types
}
void some_general_method
{
// general stuff for all types
}
};
int main()
{
ClassName< float > bar;
ClassName< int > foo;
bar.some_general_method(); // OK
foo.some_general_method(); // OK
bar.some_method(); // OK
foo.some_method(); // Compile-time ERROR
return( 0 );
}
答案 3 :(得分:2)
void some_method(){
if (std::is_floating_point<T>::value)
{
// do stuff, but only for floating point types
}
else
{
return;
}
}
我也试过了boost::is_floating_point
: -
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_floating_point.hpp>
template <typename T>
class ClassName {
typename boost::enable_if<boost::is_floating_point<T> >::type
some_method(const T & t)
{
}
};
int main()
{
ClassName<float> p; //Compiles
/* Following throws error,
error: no type named 'type' in
'struct boost::enable_if<boost::is_floating_point<int>, void>'
ClassName<int> q;
*/
}
答案 4 :(得分:1)
As detailed in this answer,您需要将成员函数作为SFINAE工作的模板(Live example at Coliru):
template <typename T>
class ClassName
{
// instance variables, etc..
public:
template <typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
void some_method()
{
// do stuff, but only for floating point types
}
};
答案 5 :(得分:0)
更新
#include <type_traits>
template <typename T>
struct ClassName
{
// instance variables, etc..
template<typename R = T>
void some_method()
{
static_assert(std::is_floating_point<R>::value,
"ClassName<T>::some_method is implemented only for floating "
"point T");
// do stuff, but only for floating point types
}
};
int main()
{
ClassName<float> f;
f.some_method();
ClassName<int> i;
i.some_method(); // <-- static_asserts here
return 0;
}