10

私の名前空間には、nsSTL コンテナーを印刷するのに役立つ関数があります。例えば:

template <typename T>
std::ostream& operator<<(std::ostream& stream, const std::set<T>& set)
{
    stream << "{";
    bool first = true;
    for (const T& item : set)
    {
        if (!first)
            stream << ", ";
        else
            first = false;
        stream << item;
    }
    stream << "}";
    return stream;
}

operator <<これは、直接印刷するのに最適です。

std::set<std::string> x = { "1", "2", "3", "4" };
std::cout << x << std::endl;

ただし、使用boost::formatは不可能です。

std::set<std::string> x = { "1", "2", "3", "4" };
boost::format("%1%") % x;

問題はかなり明らかです。Boost は、カスタムを使用operator <<して名前空間とは関係のない型を出力することを望んでいるとは考えていません。usingに宣言を追加する以外に、私の を探すboost/format/feed_args.hpp便利な方法はありますか?boost::formatoperator <<

4

4 に答える 4

5

私が実際に使用したソリューションは、Answer のものと非常に似ていますが、何に対しても機能します。

namespace ns
{

template <typename T>
class FormatWrapper
{
public:
    explicit FormatWrapper(const T& x) :
            ref(x)
    { }

    friend std::ostream& operator<<(std::ostream& stream,
                                    const FormatWrapper<T>& self
                                   )
    {
        // The key is that operator<< is name lookup occurs inside of `ns`:
        return stream << self.ref;
    }
private:
    const T& ref;
};

template <typename T>
FormatWrapper<T> Formatable(const T& x)
{
    return FormatWrapper<T>(x);
}

}

したがって、使用法は次のとおりです。

boost::format("%1%") % Formatable(x);
于 2012-10-03T13:57:53.940 に答える
4

最もクリーンな方法は、オーバーライドする各演算子に対して独自の名前空間にシン ラッパーを提供することだと思います。あなたの場合、それは次のようになります。

namespace ns
{
    namespace wrappers
    {
        template<class T>
        struct out
        {
            const std::set<T> &set;

            out(const std::set<T> &set) : set(set) {}

            friend std::ostream& operator<<(std::ostream& stream, const out &o)
            {
                stream << "{";
                bool first = true;
                for (const T& item : o.set)
                {
                    if (!first)
                        stream << ", ";
                    else
                        first = false;
                    stream << item;
                }
                stream << "}";
                return stream;
            }
        };
    }

    template<class T>
    wrappers::out<T> out(const std::set<T> &set)
    {
        return wrappers::out<T>(set);
    }
}

次に、次のように使用します。

std::cout << boost::format("%1%") % ns::out(x);
于 2012-10-03T09:14:00.507 に答える
1

あなたはこのようなことを試すことができます:

namespace boost // or __gnu_cxx
{
    using np::operator<<;
}
#include <boost/format/feed_args.hpp>
于 2012-08-18T23:35:21.387 に答える
0

すでに述べたように、問題は ADL (引数依存のルックアップ - 多くの場合 Andrew Koenig に起因しますが、彼がすべての責任を負うべきではないと思います) が原因です。

ローカル コンテキストでも、使用する予定のテンプレート関数では機能しませんoperator<<

不正行為のトリックの 1 つは、operator<<定義した を に入れることですnamespace std。それは禁止されていますが、あなたのケースではうまくいくかもしれませんが、それが使用前に置かれた場合に限り、それが問題になる可能性があります.

独自の Set テンプレートを定義するなど、さらにオプションがある場合があります。私は実験しました

    template<typename T> using Set=std::set<T>;

しかし、それなしで機能するソリューションを得ることができませんでした

    using np::operator<<;

ゆよゆっぺ提供。

于 2012-08-23T15:37:29.777 に答える