Reputation: 6707
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
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
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