簡體   English   中英

使用std :: enable_if的帶有模板重載的隱式轉換運算符T()無法編譯

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM