0

次のような汎用ストリーム演算子を実装したいベクトルクラスがいくつかあります。

template <typename T>
std::ostream& operator<<(std::ostream& os, const T& v)
{
    for (int i = 0; i < T::num_elems; ++i)
    {
        os << " " << v.a[i];
    }
    return os;
}

os << " " << ...あいまいなので、もちろんエラーが発生することを除いて、これはほとんど機能します。これを明確にして、ここで<<演算子を強制的std::に使用するにはどうすればよいですか?

または、このテンプレート化されたストリーム演算子の使用をベクター クラスだけに制限するにはどうすればよいですか? ベクトル クラスとストリーム オペレータを別の名前空間に配置しましたが、それだけでは十分ではないようです。

実際のエラー メッセージの始まり:

foo.cpp:73: error: ambiguous overload for 'operator<<' in 'os << " "'
/usr/include/c++/4.2.1/ostream:169:0 /usr/include/c++/4.2.1/ostream:169: note: candidates are: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long int) [with _CharT = char, _Traits = std::char_traits<char>] <near match>
/usr/include/c++/4.2.1/ostream:177:0 /usr/include/c++/4.2.1/ostream:177: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>] <near match>
/usr/include/c++/4.2.1/ostream:185:0 /usr/include/c++/4.2.1/ostream:185: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = char, _Traits = std::char_traits<char>]
...

さらなる明確化: ストリーム演算子はテスト ハーネス (UnitTest++) でのみ使用されており、パブリック API の一部ではありません。また、ベクター クラスは、C++ のベクターではなく、小さなカスタムの固定サイズのベクター (実際には単純な配列) です。

これを操作するために必要なベクトル クラスの 1 つの簡略化された例:

struct VectorClass {
    enum { num_elems = 16 };
    int32_t a[num_elems];
};
4

4 に答える 4

3

POD 型と配列サイズが異なる約 20 の同様のクラスがありますが、それ以外は同じです。

一般化された作業を行う名前付き関数を作成します。

template <typename T>
std::ostream& SendVectorToOstream(std::ostream& os, const T& v)
{
    for (int i = 0; i < T::num_elems; ++i)
    {
        os << " " << v.a[i];
    }
    return os;
}

operator<<これで、関数を転送することができます。

std::ostream& operator<<(std::ostream& os, const VectorClassA & v)
{
    return SendVectorToOstream( os, v );
}

std::ostream& operator<<(std::ostream& os, const VectorClassB & v)
{
    return SendVectorToOstream( os, v );
}

std::ostream& operator<<(std::ostream& os, const VectorClassC & v)
{
    return SendVectorToOstream( os, v );
}
于 2013-04-03T15:55:42.547 に答える
2

IIRC、SFINAE(Drew Dormannの回答のように)または名前空間を使用した引数依存の名前検索を使用できます:

namespace all_my_vectors
{
    struct myVector1 { int a; };
    struct myVector2 { int a; };

    template < typename Vector >
    std::ostream& operator<< (std::ostream& o, Vector const& v)
    {
        o << v.a; // look up name in std::ostream, namespace std, global namespace, namespace of v.a
        return o;
    }
}

int main()            
{
    all_my_vectors::myVector1 v1;
    all_my_vectors::myVector2 v2;

    std::cout << v1 << v2; // look up name in std::ostream, namespace std, global namespace, namespace all_my_vectors

    return 0;
}

編集:共通の基本クラスを共有している場合は、stardust_ のアプローチを使用する必要があります。

于 2013-04-03T16:33:18.733 に答える