なまもの備忘録

気になったことをつらつらと書いていきます

テンプレートフレンド演算子の宣言方法

テンプレートクラスにフレンド演算子を定義しようとした時に嵌ったのでメモ。

新たに作ったテンプレートクラスに対する演算子を定義しようとする時、それらをフレンド演算子にすることはままあると思う。管理人もそのような場面に出くわし、素直に定義しようとしたところ思いの他嵌ってしまった。

結論から言うとテンプレートフレンド演算子を定義する時は、以下のようにする(他の方法があるかどうかは調べていない)。

#include <string>

template<typename T> class test_class; //下の定義でクラステンプレートを使用しているのでこちらも事前に定義しておく必要がある。
template<typename T> bool operator==(const test_class<T>, const test_class<T>); //メンバ演算子として演算子テンプレートを定義するので前方宣言が必要

template<typename T>
class test_class
{
  public:
    test_class(std::string string):str(string){}
    std::string get_string() const
    {
    return str;
    }

    friend bool operator==<T>(const test_class<T>, const test_class<T>);  //ここで定義されるのは演算子ではなく演算子テンプレートなのでコンパイラに知らせるために<T>が必要
 //上の一行は下記コードでも代用可能
    //friend bool operator==<>(const test_class<T>, const test_class<T>);
  private:
    std::string str;
};

template<typename T>
bool operator==(const test_class<T> one, const test_class<T> two)
{
    return one.str == two.str;
}

上記コードでコメントのある行はいずれものぞくとコンパイルエラーになる。コンパイラのバージョンは

$ clang++ -v  
Apple LLVM version 8.1.0 (clang-802.0.42) 

参考

stackoverflow.com

テンプレートクラスの演算子の多重定義 - C++ Builder / Turbo C++ 質問の木