Информация об изменениях

Сообщение Re[8]: std::get(std::variant) от 25.10.2025 7:49

Изменено 25.10.2025 8:06 rg45

Re[8]: std::get(std::variant)
Здравствуйте, so5team, Вы писали:

S>Для C++17 у меня получилось что-то вроде: https://godbolt.org/z/YnehMhsT9

S>Но не покидает ощущение, что более продвинутые в современном C++ товарищи смогут сделать проще и компактнее.

Не претендую на звание более продвинутого, но свой вариант предложу, всё-таки:

https://godbolt.org/z/bGeY793rs

void has_name_aux(...);
template<typename T> auto has_name_aux(const T& t) -> decltype(t.name);
template<typename T> constexpr bool has_name_v =
    std::is_same_v<std::string, decltype(has_name_aux(std::declval<T>()))>;

template <typename...T>
std::string getName(const std::variant<T...>& v)
{
    return std::visit(
        []<typename X>(X&& x) -> std::string {
            if constexpr(has_name_v<X>)
                return x.name;
            else
                return {};
        }
        , v);
}
Re[8]: std::get(std::variant)
Здравствуйте, so5team, Вы писали:

S>Для C++17 у меня получилось что-то вроде: https://godbolt.org/z/YnehMhsT9

S>Но не покидает ощущение, что более продвинутые в современном C++ товарищи смогут сделать проще и компактнее.

Не претендую на звание более продвинутого, но свой вариант предложу, всё-таки:

https://godbolt.org/z/bGeY793rs

#include <string>
#include <variant>
#include <iostream>
#include <type_traits>

void has_name_aux(...);
template<typename T> auto has_name_aux(const T& t) -> decltype(t.name);
template<typename T> constexpr bool has_name_v =
    std::is_same_v<std::string, decltype(has_name_aux(std::declval<T>()))>;

template <typename...T>
std::string getName(const std::variant<T...>& v)
{
    return std::visit(
        []<typename X>(X&& x) -> std::string {
            if constexpr(has_name_v<X>)
                return x.name;
            else
                return {};
        }
        , v);
}

int main()
{
    struct a { std::string name{"a"};};
    struct b { };
    struct c { std::string name{"c"};};

    using Variant = std::variant<a, b, c>;

    auto test = [](const Variant& v) {
        auto const & name = getName(v);
        std::cout << (name.empty() ? "<<unnamed>>" : name) << '\n';
    };
    test(a{});
    test(b{});
    test(c{});
}