Reputation: 337
I'm trying to understand std::enable_if
, there is a example at cppreference.com , what is advantage of this using than function overloading ?
struct T {
enum { int_t,float_t } m_type;
template <typename Integer,
std::enable_if_t<std::is_integral<Integer>::value, int> = 0
>
T(Integer) : m_type(int_t) {}
>
template <typename Floating,
std::enable_if_t<std::is_floating_point<Floating>::value, int> = 0
>
T(Floating) : m_type(float_t) {} // OK
};
struct T1 {
enum { int_t, float_t } m_type;
T1(int) :m_type(int_t)
{
cout << "int ctor" << endl;
}
T1(float) :m_type(float_t)
{
cout << "float ctor" << endl;
}
};
Upvotes: 1
Views: 432
Reputation: 180935
Your two examples are not the same. With the first example, the class will except any integer or floating point type exactly. With your second example, you only take in a int
or float
meaning if you passed a long long
or double
then you have the potential for a narrowing conversion which could cause you to lose data. That doesn't matter with the code you are using, but it can and should be watched out for.
You will also get ambiguities when using a a type that could be converted to either a float
or an int
. For example
T1 foo{0l};
wont compile but
T foo{0l};
will.
Upvotes: 1
Reputation: 11516
In this case there's indeed not really an advantage, because integer types would be converted to e.g. int
first and then the correct overloaded constructor would be called.
However, imagine you want to create a function which only accepts integers. It should return the type of integer it received as argument. In that case manually creating >10 overloads is just error-prone/silly/annoying/... Instead, you'd write something like:
template <typename Integer,
std::enable_if_t<std::is_integral<Integer>::value, int> = 0>
Integer doMagic (Integer a) {
return a;
}
Upvotes: 0