cppreference.com(http://en.cppreference.com/w/cpp/types/enable_if#Notes)指出:
一个常见的错误是声明两个仅在默认模板参数上有所不同的函数模板。这是非法的,因为默认模板参数不是函数模板签名的一部分,并且声明具有相同签名的两个不同函数模板是非法的。
struct T { enum { int_t,float_t } m_type; template <typename Integer, typename = std::enable_if_t<std::is_integral<Integer>::value> > T(Integer) : m_type(int_t) {} template <typename Floating, typename = std::enable_if_t<std::is_floating_point<Floating>::value> > T(Floating) : m_type(float_t) {} // error: cannot overload };
如此真实......那么解决这个问题并实际实现上述错误代码无法实现的正确方法是什么?
答案 0 :(得分:5)
我相信这会奏效:
#include <type_traits>
struct T {
enum { int_t,float_t } m_type;
template <typename Integer,
std::enable_if_t<std::is_integral<Integer>::value>* = nullptr
>
T(Integer) : m_type(int_t) {}
template <typename Floating,
std::enable_if_t<std::is_floating_point<Floating>::value>* = nullptr
>
T(Floating) : m_type(float_t) {} // now the overload is valid
};
int main() {
T t = int{};
T t2 = float{};
(void)t;
(void)t2;
}
答案 1 :(得分:4)
答案 2 :(得分:1)
在构造函数的参数列表中的另一个伪参数中使用enable_if
:
struct T {
enum { int_t,float_t } m_type;
template <typename Integer>
T(Integer, std::enable_if_t<std::is_integral<Integer>::value>* = nullptr)
: m_type(int_t) {}
template <typename Floating>
T(Floating, std::enable_if_t<std::is_floating_point<Floating>::value>* = nullptr)
: m_type(float_t) {}
};
答案 3 :(得分:0)
我相信我找到了另一种方法来解决这个问题。由于在模板中使用浮点类型的限制,这可能不适用于浮点数,但是对于大多数其他情况仍然适用(例如区分有符号和无符号类型):
struct T {
enum { signed_t,unsigned_t } m_type;
template <typename Signed,
std::enable_if_t<std::is_signed<Signed>::value, bool> = true
>
T(Signed) : m_type(signed_t) {}
template <typename Unsigned,
std::enable_if_t<std::is_unsigned<Unsigned>::value, bool> = true
>
T(Unsigned) : m_type(unsigned_t) {}
};