Boost logo

Boost :

Subject: Re: [boost] Variadic append for std::string
From: Richard Hodges (hodges.r_at_[hidden])
Date: 2017-01-16 05:41:31


Sorry to chime in so late in the discussion.

What about a syntax similar to this?

int main()
{
    auto s = join("Hello ", ", World.", " The hex for ", 58, " is ", std::hex, 58);
    std::cout << s << std::endl;

    s = join(separator(" : "), "a", "b", std::hex, 200 , std::quoted("banana"));
    std::cout << s << std::endl;

}

Which would produce the following output:

Hello , World. The hex for 58 is 3a
a : b : c8 : “banana"

sample implementation (io manipulators may be incomplete, some efficiency gains could be made by re-implementing ostringstream more cleverly):

#include <sstream>
#include <iostream>
#include <iomanip>

namespace detail {
    template<class SepStr>
    struct separator_object
    {
        template<class T>
        std::ostream& operator ()(std::ostream& s, T&& t) const
        {
            return s << sep << t;
        }

        //
        // other iomanp specialisations here
        //
        std::ostream& operator ()(std::ostream& s, std::ios_base&(*t)(std::ios_base&)) const
        {
            t(s);
            return s;
        }

        SepStr const& sep;
    };

    struct no_separator_object
    {
        template<class T>
        std::ostream& operator ()(std::ostream& s, T&& t) const
        {
            return s << t;
        }
    };

    template<class Separator, class String, class...Rest>
    auto join(Separator&& sep, String&& s, Rest&&...rest)
    {
        std::ostringstream ss;
        ss << s;
        using expand = int [];
        void(expand{0,
                    ((sep(ss, rest)), 0)...
        });
        return ss.str();
    };

}

template<class Sep>
static constexpr auto separator(Sep const& sep)
{
    using sep_type = std::remove_const_t<std::remove_reference_t<Sep>>;
    return detail::separator_object<sep_type> { sep };
}

template<class SepObject, class String, class...Rest>
auto join(const detail::separator_object<SepObject>& sep, String&& s, Rest&&...rest)
{
    return detail::join(sep,
                        std::forward<String>(s),
                        std::forward<Rest>(rest)...);
};

template<class String, class...Rest>
auto join(String&& s, Rest&&...rest)
{
    return detail::join(detail::no_separator_object(),
                        std::forward<String>(s),
                        std::forward<Rest>(rest)...);
};

int main()
{
    auto s = join("Hello ", ", World.", " The hex for ", 58, " is ", std::hex, 58);
    std::cout << s << std::endl;

    s = join(separator(" : "), "a", "b", std::hex, 200 , std::quoted("banana"));
    std::cout << s << std::endl;

}


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk