如何在模板中同时允许浮点数和整数类型但不允许 bool

How can I allow both floating-point and integer types but disallow bool in a template

假设我有一些数字 class,带有一个允许“数字”(故意引号)的构造函数。 在内部,它存储为一个浮点值,所以我只想要一个数字作为参数,所以我拒绝对除浮点数以外的其他类型进行实例化:

template<typename T>
struct MyClass
{
   MyClass( T value ) : _v(value)
   {
      static_assert( std::is_floating_point<T>::value, "only numbers!" );
   }
   double _v;
};

然而,这很烦人,因为我总是要写 MyClass m(42.);,有时我会忘记,或者其他什么,我希望能够只写 MyClass m(42);。 所以我添加了整数类型:

template<typename T>
struct MyClass
{
   MyClass( T value ) : _v(value)
   {
      static_assert( std::is_floating_point<T>::value || std::is_integral<T>::value, "only numbers!" );
   }
   double _v;
};

这样做的缺点是 std::is_integral 也允许 bool。 而且我觉得允许从布尔值自动转换为数值完全是胡说八道(当然是在那种情况下)。

MyClass m(true);  // no way !

问题:如何允许浮点数和整数类型,而禁用布尔类型? (没有 std::is_boolean 可用)

您可以用 std::is_same 检查 bool。例如

MyClass( T value ) : _v(value)
{
   static_assert( ( std::is_floating_point<T>::value || 
                    std::is_integral<T>::value ) && 
                  !std::is_same<T, bool>::value, "only numbers!" );
}

在我看来,最简单的方法是模板构造函数 + bool 的显式删除构造函数。看看这个 - 它非常明确并且可以做你想做的事:

#include <type_traits>

template<typename T>
struct MyClass
{
    template<class U>
    MyClass(U value) : _v(value)
    {
    }

    MyClass(bool) = delete;

   double _v;
};

int main() {
    auto foo = MyClass<double>(3);
    auto bar = MyClass<int>(1);
    auto baz = MyClass<double>(true); // fails
}