I have a function in my namespace ns that helps me print STL containers. For example:
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;
}
This works great for printing with operator << directly:
std::set<std::string> x = { "1", "2", "3", "4" };
std::cout << x << std::endl;
However, using boost::format is impossible:
std::set<std::string> x = { "1", "2", "3", "4" };
boost::format("%1%") % x;
The problem is fairly obvious: Boost has no idea that I would like it to use my custom operator << to print types which have nothing to do with my namespace. Outside of adding a using declaration into boost/format/feed_args.hpp, is there a convenient way to make boost::format look for my operator <<?
The solution I actually went with is quite similar to Answeror's, but it works for anything:
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);
}
}
So usage is:
boost::format("%1%") % Formatable(x);
                        I think the most clean way is to provide a thin wrapper in your own namespace for each of the operators you want to override. For your case, it can be:
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);
    }
}
Then use it like this:
std::cout << boost::format("%1%") % ns::out(x);
                        You can try something like this:
namespace boost // or __gnu_cxx
{
    using np::operator<<;
}
#include <boost/format/feed_args.hpp>
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With