#ifndef STR_HPP
#define STR_HPP


#include <sstream>


#define STR(VALUES) \
    ((std::ostringstream &)(std::ostringstream() << VALUES)).str()

#define STR_JOIN(JOIN, IT, ITERABLE) \
    [&] { \
        auto const & iterable = ITERABLE; \
        auto const & join = JOIN; \
        std::ostringstream oss; \
        auto first = true; \
        for (auto & it : iterable) { \
            if (!first) \
                oss << join; \
            oss << IT; \
            first = false; \
        } \
        return oss.str(); \
    }()

#define STR_CASE(CASE) \
    case CASE: return #CASE;

#define STR_COND(VALUE, CASE) \
    (VALUE) == (CASE) ? #CASE :

#define STR_INGIFY1(X) #X
#define STR_INGIFY2(X) STR_INGIFY1(X)

#define STR_HERE(VALUES) \
    STR(__FILE__ << ":" << STR_INGIFY2(__LINE__) ": " << VALUES)


#endif // STR_HPP
