kebs
kebs

Reputation: 6707

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

Say I have some numerical class, with a constructor that allows a "number" (quotes on purpose). Inside, it is stored as a floating-point value, so I want only a number as argument, so I denied instanciation on other types than floating-points:

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

However, this is annoying, because I always have to write MyClass m(42.); and sometimes I forget, or whatever, and I want to be able to write just MyClass m(42);. So I added integral types:

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;
};

The downside of this is that std::is_integral also allows bool. And I feel that allowing automatic conversion from a boolean value to a numerical value is complete nonsense (in that situation of course).

MyClass m(true);  // no way !

Question: how can I allow both floating-point and integer types, and disable boolean type? (No std::is_boolean available)

Upvotes: 2

Views: 616

Answers (2)

bartop
bartop

Reputation: 10315

In my opinion the simplest way is template constructor + explicitly deleted constructor for bool. Take a look at this - it is pretty explicit and does what you want:

#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
}

Upvotes: 2

songyuanyao
songyuanyao

Reputation: 172964

You can check bool with std::is_same. E.g.

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!" );
}

Upvotes: 3

Related Questions