簡體   English   中英

嵌套在 class 中的枚舉上的運算符重載

[英]Operator overloading on an enum nested in a class

問題

給定以下代碼:

template <typename T>
struct dummy {
  enum enumenum { a = 1, b = 2, c = 4 };
};

int main() { 
    // I want this line to expands as : 
    // dummy<double>::enumenum a = operator~(dummy<double>::a);
    auto a = ~dummy<double>::a;
}

如何在enumenum上重載運算符? 我正在使用標准 C++14。

我試過的

一個天真的實現:

template <typename T>
typename dummy<T>::enumenum 
operator~(typename dummy<T>::enumenum a) {
  return static_cast<typename dummy<T>::enumenum>(operator~(a));
}

不幸的是,有問題的行擴展為:

int a = ~static_cast<int>(dummy<double>::a);

這意味着未使用運算符(這是默認行為)。 是不是因為 ADL 在 struct 命名空間中找不到正確的operator~() (這甚至是一件事嗎?)?

然后我嘗試了:(注意friend

template <typename T>
struct dummy {
  enum enumenum { a, b, c };
  
  friend enumenum operator~(enumenum a) { 
    return static_cast<enumenum>(~a);
  }
};

這實際上有效並擴展為:

template <>
struct dummy<double> {
  enum enumenum {
    a = static_cast<unsigned int>(1),
    b = static_cast<unsigned int>(2),
    c = static_cast<unsigned int>(4)
  };

  friend inline dummy<double>::enumenum operator~(dummy<double>::enumenum a) {
    return static_cast<dummy<double>::enumenum>(operator~(a));
  }
};

int main()
{
  dummy<double>::enumenum a = operator~(dummy<double>::a);
}

這是我想要的行為。 除了,如果我不想在 class 正文中定義運算符怎么辦。

所以我嘗試了:

template <typename T>
struct dummy {
  enum enumenum { a = 1, b = 2, c = 4 };
  
  // if inline : inline function 'operator~' is not defined [-Wundefined-inline]
  // and adding inline to the template below does not help
  friend enumenum operator~(enumenum a);
};

template <typename T>
typename dummy<T>::enumenum 
operator~(typename dummy<T>::enumenum a) {
  return static_cast<typename dummy<T>::enumenum>(~a);
}

int main() { 
    auto a = ~dummy<double>::a; 
}

上面的代碼擴展為:

template<>
struct dummy<double>
{
  enum enumenum
  {
    a = static_cast<unsigned int>(1), 
    b = static_cast<unsigned int>(2), 
    c = static_cast<unsigned int>(4)
  };
  
  friend dummy<double>::enumenum operator~(dummy<double>::enumenum a);
};

int main()
{
  dummy<double>::enumenum a = operator~(dummy<double>::a);
}

這編譯,但鏈接:編輯。 我相信它沒有鏈接,因為模板沒有實例化,因此在鏈接時失敗(類似於上面的幼稚實現)。

結論

即使我以某種方式找到了實現我想要的方法,但如果我不想在 class 定義中定義運算符怎么辦

提前致謝。

這編譯,但不鏈接!

編譯但不鏈接,因為您聲明了一個非模板運算符(它在模板結構內但不是模板函數)

friend enumenum operator~(enumenum a);

然后你定義一個模板

template <typename T>
typename dummy<T>::enumenum 
operator~(typename dummy<T>::enumenum a) {
  return static_cast<typename dummy<T>::enumenum>(~a);
}

並且模板定義不能匹配非模板聲明。

您可以嘗試將 function 聲明為模板之一

template <typename T>
struct dummy
 {
   enum enumenum { a = 1, b = 2, c = 4 };

   template <typename U>
   friend typename dummy<U>::enumenum
      operator~ (typename dummy<U>::enumenum const & a);
 };

template <typename T>
typename dummy<T>::enumenum 
      operator~ (typename dummy<T>::enumenum const & a)
 { return static_cast<typename dummy<T>::enumenum>(~a); }

int main ()
 { 
   auto a = ~dummy<double>::a; 
 }

但是,不幸的是,這個編譯但是,調用~運算符如下

 ~dummy<double>::a;

不被稱為模板 function 因為模板參數T無法推斷,因為它在未推斷的上下文中(在最后一個::之前),正如 Benny K 在評論中指出的那樣。

因此,模板operator~()dummy<double>::a轉換為int並應用int~運算符(類型為 result int )。

您可以通過顯式調用 function operator~()

 auto a = operator~(dummy<double>::a); 

你應該得到一個“沒有匹配的 function 調用'operator~'”錯誤(帶有注釋“注意:候選模板被忽略:無法推斷模板參數'T'”)或類似的東西。

要使此解決方案有效,您必須說明 class 的類型,以避免模板扣除

 auto a = operator~<double>(dummy<double>::a); 

現在,您可以驗證a是一個dummy<double>::enumenum

 static_assert( std::is_same<decltype(a), dummy<double>::enumenum>::value, "!" );

但是,顯然,這不是一個令人滿意的解決方案(如果您忘記避免簡單地使用~ ,這將非常危險)。

否則,您可以將運算符定義為非模板

template <typename T>
struct dummy
 {
   enum enumenum { a = 1, b = 2, c = 4 };

   friend enumenum operator~ (enumenum const & a);
 };

dummy<double>::enumenum 
      operator~(dummy<double>::enumenum const & a)
 { return static_cast<dummy<double>::enumenum>(~a); }

int main ()
 { 
   auto a = ~dummy<double>::a; 
 }

但是您必須為每個dummy<T>類型定義不同的運算符。

恕我直言,最簡單、安全和優雅的解決方案是您的工作解決方案:在結構內聲明/定義運算符。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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