Сообщение Re: std::get(std::variant) от 27.10.2025 7:53
Изменено 27.10.2025 8:01 Chorkov
Re: std::get(std::variant)
Здравствуйте, Marty, Вы писали:
Еще один вариант: перенос специализации c операторов () визитора, на специализацию свободных функций:
Плюсы:
В случае, когда конкретный тип заренее известве, буджут сразу вызваны функции для конкретных типов, избегая диспетчеризации в visit.
Можно писать код в "распеределенном" режиме, оперделяя getName для новых классов рядом с классом.
с++17 — достаточно. Можно и на c++11, но специализация по признаку наличия поля — сильно многословнее.
Еще один вариант: перенос специализации 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 операторов () визитора, на специализацию свободных функций:
Плюсы:
В случае, когда конкретный тип заренее известве, буджут сразу вызваны функции для конкретных типов, избегая диспетчеризации в visit.
Можно писать код в "распеределенном" режиме, оперделяя getName для новых классов рядом с классом.
с++17 — достаточно. Можно и на c++11, но специализация по признаку наличия поля — сильно многословнее.
Еще один вариант: перенос специализации 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, но специализация по признаку наличия поля — сильно многословнее.