![](/img/trans.png)
[英]Using std::enable_if to declare a parenthesis operator with variadic template args
[英]Implicit conversion operator T() with template overloads using std::enable_if fail to compile
我正在C ++ 17中编写一个类,我希望对浮点类型以及某些自定义类型使用重载转换运算符。 这是可重现的示例。 我还需要使用模板添加更多的转换,但是如果我可以解决这些转换,则其余的应该类似。
class A {
};
class B : public A {
};
class C: public A {
};
class Missing {
public:
Missing() {}
Missing(Missing &) = default;
template<typename T,typename=typename std::enable_if_t<std::is_floating_point_v<T>, T>>
explicit constexpr operator T() const {
return static_cast<T>(NAN);
}
template<typename T, class = typename std::enable_if_t<std::is_base_of_v<A, T>, T>>
explicit operator T() const {
return T();
}
};
但是在使用带有std = c ++ 17标志的gcc 8.2进行编译时,出现以下错误:
<source>:25:12: error: 'template<class T, class> Missing::operator T() const' cannot be overloaded with 'template<class T, class> constexpr Missing::operator T() const'
explicit operator T() const {
^~~~~~~~
<source>:20:22: note: previous declaration 'template<class T, class> constexpr Missing::operator T() const'
explicit constexpr operator T() const {
^~~~~~~~
Compiler returned: 1
我认为使用enable_if
可以防止运算符针对同一类型进行重载,但看起来编译器在第一遍就没有考虑enable_if
。 我不确定我的语法是否正确。 任何帮助,将不胜感激。 已经在这里住了一段时间了。
更新 :
尝试将运算符更新为
template<typename T>
constexpr explicit operator std::enable_if_t<std::is_floating_point_v<T>, T>() const {
return static_cast<T>(NAN);
}
template<typename T>
explicit operator std::enable_if_t<std::is_base_of_v<A, T>, T>() const {
return T();
}
但是现在,在尝试使类浮动时:
int main() {
Missing m;
float a = static_cast<float>(m);
}
我收到一个错误:
<source>:34:35: error: invalid static_cast from type 'Missing' to type 'float'
float a = static_cast<float>(m);
问题是您用相同的默认参数两次声明了相同的成员模板。 该错误发生在任何实例化之前,因此甚至不查看默认参数。
解决此问题的第一个动力是将enable_if_t
移出参数,并使其成为运算符的返回类型:
template<typename T>
explicit constexpr operator std::enable_if_t<std::is_floating_point_v<T>, T>>() const ...
但这不起作用,因为T
现在是未推论的上下文。
所以其他的方式,使两个模板不同的是添加一个虚拟参数与defalut值其中之一 。
template<typename T,
typename = std::enable_if_t<std::is_floating_point_v<T>, T>,
bool = true>
explicit constexpr operator T() const ...
另一个模板应保留原样。
由于两个模板具有不同数量的模板参数,因此不再将它们视为相同。
另一种方法是将推导的模板参数定义为默认指针:
template
<
typename T,
std::enable_if_t<std::is_floating_point_v<T>>* = nullptr
>
explicit constexpr operator T() const {
return static_cast<T>(NAN);
}
我发现这是一种简洁可靠的方法,可以有选择地启用方法,运算符和构造函数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.