LINUX.ORG.RU

История изменений

Исправление Siborgium, (текущая версия) :

Кратко: https://godbolt.org/z/K96z6onrb

Для Ъ:

/* Визитор, пишется один раз в хэдере */
template <typename ... Ts> struct Overloaded: Ts... { using Ts::operator()...; };
template <typename ... Ts> Overloaded(Ts...) -> Overloaded<Ts...>;

/* Актуальный код */
template <typename T>
concept HasToString = requires (T trait, std::string& result, const State & state) {
    result += trait.toString(state);
};

template <typename ... Traits>
void traitsToString(const State& voxel, std::string& result, Traits&& ... traits) {
    Overloaded impl {
        [&](HasToString auto&& trait){ result += trait.toString(voxel); },
        [](auto&&){ /* noop */ }
    };
    (impl(traits), ...);
}

Можно, конечно, и без визитора, а просто через if constexpr, но там нужно будет remove_cvref_t делать.

Кстати, делать string += toString так себе идея. Лучше уж тогда stringstream и передавать по ссылке в toString, чтобы строки лишний раз не создавать.

Исходная версия Siborgium, :

Кратко: https://godbolt.org/z/K96z6onrb

Для Ъ:

/* Визитор, пишется один раз в хэдере */
template <typename ... Ts> struct Overloaded: Ts... { using Ts::operator()...; };
template <typename ... Ts> Overloaded(Ts...) -> Overloaded<Ts...>;

/* Актуальный код */
template <typename T>
concept HasToString = requires (T trait, std::string& result, const State & state) {
    result += trait.toString(state);
};

template <typename ... Traits>
void traitsToString(const State& voxel, std::string& result, Traits&& ... traits) {
    Overloaded impl {
        [&](HasToString auto& trait){ result += trait.toString(voxel); },
        [](auto&&){ /* noop */ }
    };
    (impl(traits), ...);
}

Можно, конечно, и без визитора, а просто через if constexpr, но там нужно будет remove_cvref_t делать.

Кстати, делать string += toString так себе идея. Лучше уж тогда stringstream и передавать по ссылке в toString, чтобы строки лишний раз не создавать.