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

Сообщение Re: std::get(std::variant) от 27.10.2025 7:53

Изменено 27.10.2025 8:01 Chorkov

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

Еще один вариант: перенос специализации c операторов () визитора, на специализацию свободных функций:

struct a { std::string name{"a"};};
struct b { };
struct c { std::string name{"c"};};
struct d { };
using Variant = std::variant<a, b, c, d>;


template<typename T>
auto getName(const T& v) -> decltype(v.name) { return v.name; }  // можнос специализировать типы по наличию поля

inline std::string getName(const d& v) { return "type d"; }  // можнос специализировать конкретные типы

// Все варианты типов, что не подошли под спефиализации. Наименее приоритетный вариант.
inline std::string getName(...) { return ""; }

template<typename ...T>
std::string getName(const std::variant<T...>& v) 
{ 
    return std::visit( [](const auto& vi)->std::string { return getName(vi); }, v ); 
}


Плюсы:
В случае, когда конкретный тип заренее известве, буджут сразу вызваны функции для конкретных типов, избегая диспетчеризации в visit.
Можно писать код в "распеределенном" режиме, оперделяя getName для новых классов рядом с классом.
с++17 — достаточно. Можно и на c++11, но специализация по признаку наличия поля — сильно многословнее.
Re: std::get(std::variant)
Здравствуйте, Marty, Вы писали:

Еще один вариант: перенос специализации c операторов () визитора, на специализацию свободных функций:

struct a { std::string name{"a"};};
struct b { };
struct c { std::string name{"c"};};
struct d { };
using Variant = std::variant<a, b, c, d>;


template<typename T>
auto getName(const T& v) -> decltype(v.name) { return v.name; }  // можнос специализировать типы по наличию поля

inline std::string getName(const d& v) { return "type d"; }  // можнос специализировать конкретные типы

// Все варианты типов, что не подошли под спефиализации. Наименее приоритетный вариант.
inline std::string getName(...) { return ""; }

template<typename ...T>
std::string getName(const std::variant<T...>& v) // Работа с variant обязательно шаблонная. Иначе можно попасть в рекурсивный вызов для не специализированного класса.
{ 
    return std::visit( [](const auto& vi)->std::string { return getName(vi); }, v ); 
}


Плюсы:
В случае, когда конкретный тип заренее известве, буджут сразу вызваны функции для конкретных типов, избегая диспетчеризации в visit.
Можно писать код в "распеределенном" режиме, оперделяя getName для новых классов рядом с классом.
с++17 — достаточно. Можно и на c++11, но специализация по признаку наличия поля — сильно многословнее.