簡體   English   中英

如何為類模板定義非成員運算符重載?

[英]How to define non-member operator overload for class template?

我有一個類模板,其構造函數采用std :: chrono :: duration,因為我希望能夠使用chrono_literals來構造它。 現在,我正在嘗試定義非成員運算符重載,但我無法使用持續時間構造函數:

#include <chrono>
#include <iostream>

using namespace std;

template <int n> struct MyClass {
  MyClass() = default;

  template <typename REP, typename PERIOD>
  constexpr MyClass(const std::chrono::duration<REP, PERIOD> &d) noexcept
      : num(d.count()) {}

  int num = n;
};

template <int n> bool operator==(MyClass<n> lhs, MyClass<n> rhs) {
  return lhs.num == rhs.num;
}

int main(int argc, char *argv[]) {
  using namespace std::literals::chrono_literals;

  MyClass<0> m1(10ns);

  if (m1 == 10ns)
    cout << "Yay!" << endl;
  return 0;
}

gcc拒絕我的重載就是這個錯誤:

main.cpp:34:12: error: no match for ‘operator==’ (operand types are ‘MyClass<0>’ and ‘std::chrono::nanoseconds {aka std::chrono::duration<long int, std::ratio<1l, 1000000000l> >}’)
     if (m1 == 10ns)
         ~~~^~~~~~~
main.cpp:23:6: note: candidate: template<int n> bool operator==(MyClass<n>, MyClass<n>)
 bool operator == (MyClass<n> lhs, MyClass<n> rhs)
      ^~~~~~~~
main.cpp:23:6: note:   template argument deduction/substitution failed:
main.cpp:34:15: note:   ‘std::chrono::duration<long int, std::ratio<1l, 1000000000l> >’ is not derived from ‘MyClass<n>’
     if (m1 == 10ns)
               ^~~~

有沒有辦法讓這項工作?

更簡單的方法是將函數放在類中:

template <int n> struct MyClass {
  MyClass() = default;

  template <typename REP, typename PERIOD>
  constexpr MyClass(const std::chrono::duration<REP, PERIOD> &d) noexcept
      : num(d.count()) {}

    friend bool operator==(MyClass lhs, MyClass rhs) { return lhs.num == rhs.num; }


  int num = n;
};

演示

這不起作用:

if (m1 == 10ns)

因為當我們在MyClass<0>std::chrono::duration<???, std::nano>之間查詢operator== ,我們找到的唯一運算符是:

template <int n>
bool operator==(MyClass<n> lhs, MyClass<n> rhs);

這不是匹配 - 對於任何n10ns不是MyClass<n> ,因此模板推斷失敗。 要編寫非成員相等運算符,您需要匹配任何持續時間:

template <int n, class R, class P> bool operator==(MyClass<n>, duration<R,P> );

在兩個方向:

template <int n, class R, class P> bool operator==(duration<R,P>, MyClass<n> );

除了您已經擁有的運營商。 這會奏效,有時甚至是必要的。

一種更簡單的方法是將operator==聲明為非成員朋友,就像Jarod42建議的那樣。 這個工作的原因是你的非成員函數是一個函數模板,朋友不是 因此在m1 == 10ns查找找到函數:

bool operator==(MyClass<0>, MyClass<0>);

10ns可以轉換為MyClass<0> ,這在此上下文中是允許的,因此這是有效的。 轉換非常便宜,所以不用擔心。 而你只需編寫一個函數。

暫無
暫無

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

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