5

いくつかのメンバー型を定義するテンプレート クラスがあります。独自のテンプレート引数に基づいてstd::map定義する方法に似ていますが、私の場合、型はより複雑であるため、ネストされたクラスとして定義されています。value_type

operator<<デバッグのために、そのタイプを定義したいと思います。しかし、コンパイラは、外側のテンプレートのテンプレート パラメーターを推測できないと言っています。

私の実際のコードは次の例のように不自然ではありませんが、この不自然な例は、私が試したアプローチとそれがどのように失敗するかを示しています。

#include <iostream>

template <typename Value> class Outer;

template <typename Value>
std::ostream &operator<<(std::ostream &, const typename Outer<Value>::Inner &);

template <typename Value>
class Outer {
  public:
    struct Inner {
    Value x;
    };

    void PrintSomething(Value v) {
    // the real program does something useful with the inner class, of course
    Inner inner = { v };
    std::cout << "Inner = " << inner << std::endl; // <---- THIS SAYS IT CAN'T FIND operator<<
    };
};

template <typename Value>
std::ostream &operator<<(std::ostream &s, const typename Outer<Value>::Inner &v) {
    return s << v.x;
}

int main() {
    Outer<int> o;
    o.PrintSomething(42);
    return 0;
}

これは、問題を再現するための完全なサンプルです。コンパイラ (私はそれらのうちの 3 つを試しました) はoperator<<、 type の 2 番目の引数を取るオーバーロードはないと言いOuter<int>::Innerます。他のオーバーロードを持たない別の関数で同じことを試みると、代わりにC2783: could not deduce template argument for 'identifier'、gcc と clang は、2 番目の引数を取るオーバーロードがないと言い続けますOuter<int>::Inner)。

それで、それが正しい(メンバーとして定義できない)引数operator<<を取ることOuter<Value>::Innerを定義する方法はありますか?Value

注: いくつかのコンパイラでコンパイルする必要があり、そのうちのいくつかには C++11 機能がないため、C++03 である必要があります。

4

1 に答える 1

6

そこにあるのは、いわゆる非演繹コンテキストです。どのようValueに推測することができますか?クラス テンプレートを部分的に特殊化して、コンパイラがすべての可能なインスタンス化を試みてテストすることさえ事実上不可能にすることができます (そのインスタンス化には..まあ、無限があります)。

回避策は 2 つあります。 を削除InnerするOuteroperator<<、インライン フレンドを作成します。後者は、人々が行く通常の方法です。

template<class T>
struct Outer{
  struct Inner{
    T value;
    friend std::ostream& operator<<(std::ostream& os, Inner const& v){
      return os << v.value:
    }
  };
  // ...
};
于 2013-03-14T14:48:18.490 に答える