6

テンプレート化されたコンテナー クラスであるという点で、boost::any に似たクラスがあります。含まれている値を文字列に書き込むメソッドが欲しいです。ただし、含まれている型がストリーム挿入演算子を提供しない場合、コンパイルに失敗するのではなく、メソッドがデフォルトの文字列を返すようにしたいと考えています。以下は私がやってきた限りであり、私がやろうとしていることを明確にする必要があります:

namespace W {
    namespace hide {
        template <typename T>
        std::ostream& operator<<(std::ostream& out, const T& t) {
            return std::operator<<(out, typeid(T).name());
        }
    }

    template <typename T> struct C {

        T t_;

        std::string ToString() const {
            using namespace hide;
            std::ostringstream oss;
            oss << t_;
            return oss.str();
        }
    };
}

これはかなりうまく機能しますが、いくつかの注意事項があります。たとえば、クラスにオーバーロードされた挿入演算子を実際に提供したい場合、その演算子はクラスと同じ名前空間にあるか、考慮される W 名前空間にある必要があります。

また、char や std::string など、メンバー以外の std::operator<< を持つ型にも問題があります。T がこれらの型の 1 つである場合、oss << t_上記の行はあいまいになります。これは、W 名前空間内にこれらの型のオーバーロードを追加することで回避できます。次に例を示します。

std::ostream& operator << (std::ostream& out, const std::string& s) {
    return std::operator <<(out, s);
}

私の質問は、これよりも良い方法を見つけた人はいますか? std::string のようなものに独自のオーバーロードを追加する必要があるのはなぜですか? これはすべて標準に従ってサポートされていますか、それとも非標準の動作を利用していますか? (g++ 4.3.3 でテストしています)

4

1 に答える 1

3

以下は、少し前にコンパイラ構築クラスで見た覚えのあるコードです。私はそれが特に賢いと思ったので(「クリーン」ではないにしても)、それを持ち続けました。

http://www.cs.colorado.edu/~main/a++/tree.hから

   // If data of type T can be printed with the usual << operator, then
   // print<T>(out, p) will interpret *p as a T object and print its
   // value to out.  Otherwise, a message is printed to out, indicating
   // that objects of type T are not printable.
   template<typename T> void print(std::ostream& out, const void* p)
    {
    // The first part of this code sets an enum value, is_printable, to
    // be 1 if the data type T can be printed with the usual <<
    // operator.  Otherwise, is_printable is set to zero.  The programming
    // technique is based on a note from Herb Sutter at
    // http://www.gotw.ca/gotw/071.htm
    class object
    {
    public:
        object(T convert) { };
    };
    char operator << (std::ostream&, const object&);
    enum { is_printable = sizeof(std::cout << (*static_cast<T*>(0))) == sizeof(char) ? 0 : 1 };

        // Notice that the boolean expression in the if-statement is known at
    // compile time, so that only one of the two output statements will be
    // compiled into object code.
    if (is_printable)
        out << *static_cast<const T*>(p);
    else
        out << "(value of type " << typeid(T).name() << " cannot be printed)";
    }

コンテナー オブジェクトを作成するときは、変数の print 関数へのポインターを保持します。

void (*printer)(std::ostream&, const void*); 
printer = print<T>;

その後、可能であれば、printer() 関数を使用して、含まれている値を表示します。

お役に立てれば。

于 2010-01-08T20:24:26.383 に答える