简体   繁体   English

使用std :: enable_if的带有模板重载的隐式转换运算符T()无法编译

[英]Implicit conversion operator T() with template overloads using std::enable_if fail to compile

I am writing a class in C++17 which I would like overload conversion operator for floating types as well as for some custom types. 我正在C ++ 17中编写一个类,我希望对浮点类型以及某些自定义类型使用重载转换运算符。 Here is the reproducible example. 这是可重现的示例。 There are many more conversions that I need to add with templates, but if I can resolve these, the rest should be similar. 我还需要使用模板添加更多的转换,但是如果我可以解决这些转换,则其余的应该类似。

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


};

However on compilation with gcc 8.2 with std=c++17 flag, I get the following error: 但是在使用带有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

I would think that using enable_if would prevent the operators from overloading for the same type, but looks like the compiler isn't looking at the enable_if on the first pass. 我认为使用enable_if可以防止运算符针对同一类型进行重载,但看起来编译器在第一遍就没有考虑enable_if I am not sure if I have the right syntax. 我不确定我的语法是否正确。 Any help would be appreciated. 任何帮助,将不胜感激。 Been at this for some time now. 已经在这里住了一段时间了。


Update : 更新

Tried updating the operators to 尝试将运算符更新为

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

But now, on trying to cast the class to float: 但是现在,在尝试使类浮动时:

int main() {
    Missing m;
    float a = static_cast<float>(m);
}

I get an error: 我收到一个错误:

<source>:34:35: error: invalid static_cast from type 'Missing' to type 'float'

     float a = static_cast<float>(m);

The problem is that you are declaring the same member template twice, with different default arguments. 问题是您用相同的默认参数两次声明了相同的成员模板。 The error happens before any instantiation so the default arguments are not even looked at. 该错误发生在任何实例化之前,因此甚至不查看默认参数。

The first impulse to solve this would be moving enable_if_t out of the arguments and making it the return type of the operator: 解决此问题的第一个动力是将enable_if_t移出参数,并使其成为运算符的返回类型:

template<typename T>
explicit constexpr operator std::enable_if_t<std::is_floating_point_v<T>, T>>() const ...

But this doesn't work because T is undeduced context now. 但这不起作用,因为T现在是未推论的上下文。

So the other way to make the two templates different is to add a dummy parameter with a defalut value to one of them. 所以其他的方式,使两个模板不同的是添加一个虚拟参数与defalut值其中之一

template<typename T,
         typename = std::enable_if_t<std::is_floating_point_v<T>, T>,
         bool = true>
explicit constexpr operator T() const ...

The other template should be left as is. 另一个模板应保留原样。

With the two templates having different number of template parameters, they are no longer considered identical. 由于两个模板具有不同数量的模板参数,因此不再将它们视为相同。

Another way is to define the deduced template argument to be a defaulted pointer: 另一种方法是将推导的模板参数定义为默认指针:

template
<
  typename T, 
  std::enable_if_t<std::is_floating_point_v<T>>* = nullptr
>
explicit constexpr operator T() const {
  return static_cast<T>(NAN);
}

I find this to be a concise and reliable way to optionally enable methods, operators and constructors. 我发现这是一种简洁可靠的方法,可以有选择地启用方法,运算符和构造函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM