2017-09-14 18 views
6

私は「宣言以外のテンプレートクラスのフレンドテンプレート関数を定義する方法」(SO/cppreference)を見つけましたが、ミックスに別の内部非テンプレートクラスを追加するとどうするのですか?両方のクラス以外のテンプレートクラスの内部で、非テンプレートクラス内で宣言されたフレンド関数を定義する方法はありますか?

I.e. (外部)operator<<は、以下の例からclass Internalで宣言された定義する方法:

#include <iostream> 

template <typename T> 
class External { 
public: 
    explicit External(T initial) : value{initial} {} 
    class Internal { 
    public: 
     Internal(const External& e) : internal_value{e.value} {} 

    private:   
     friend std::ostream& operator<<(std::ostream& os, const Internal& i); 
     // ^^^ this one 
     /* body 
     { 
      return os << i.internal_value; 
     } 
     */ 

     T internal_value; 
    }; 

    friend std::ostream& operator<<(std::ostream& os, const External& e) 
    { 
     return os << Internal{e}; 
    } 
private: 
    T value; 
}; 

int main() 
{ 
    std::cout << External<int>{5}; 
} 
+0

:保守可能な方法でそれを達成するための方法は、オペレータ定義インラインを維持し、代わりにそこに仕事をして、(は、テンプレートパラメータに依存です)メンバ関数へのデリゲートすることです@StoryTellerルックアップルールは何ですか? –

+0

@RichardHodges - あなたは何を知っているのですか?私はルックアップのルールを混乱させる可能性があります。それは、OPのインラインフレンド機能であり、ADLによってのみ検出されます。 – StoryTeller

+3

これは広すぎると投票した人は...? –

答えて

6

はここで問題です。実際にはExternalはテンプレートであり、Internalは依存型です。友人機能はテンプレート自体ではありません。奇妙に見えるかもしれませんが、テンプレートパラメータに依存しません。

インラインで定義すると、テンプレートの各特殊化によって、関連するfriend関数も作成されます。しかし、インラインでないときは、各専門分野のオペレータの定義をに明示的に指定する必要があります。。また、関数はテンプレートではないので、テンプレートではできません。

ですから、テンプレート宣言の後にこれを追加した場合:それが構築されます

std::ostream& operator<<(std::ostream& os, External<int>::Internal const& i) 
{ 
    return os << i.internal_value; 
} 

。ご覧のとおり、具体的な型だけが関数内で使用されています。

明らかに、これはあまり解決策ではありません。すべての賢明な人は、Externalの専門化も同様に友人定義を生成したいと思うでしょう。

class Internal { 
public: 
    Internal(const External& e) : internal_value{e.value} {} 

private: 
    std::ostream& print(std::ostream&) const; 
    friend std::ostream& operator<<(std::ostream& os, Internal const& i) 
    { 
     return i.print(os); // Short and sweet on account of being inline 
    } 

    T internal_value; 
}; 

//.... 

template<typename T> 
std::ostream& External<T>::Internal::print(std::ostream& os) const { 
    // Provided outside of the class definition, can be as verbose as you like 
    return os << internal_value; 
} 
+2

hah!あなたは私の前の瞬間に答えを得たようです。あなたの答えはより完全です。私は私を削除します。 –

関連する問題