/
nantonenko95
/
constraint_variant
Обзор
Документация
Войти
/
nantonenko95
/
constraint_variant
Код
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
constraint_variant.cpp
111 строк
3 KB
nantonenko95
update constraint_variant.cpp
05 июл 2025, 14:04
05 июл 2025, 14:04
5c51855
Код
Авторство
О чём код?
// Type your code here, or load an example. #include <iostream> #include <vector> #include <functional> #include <variant> using namespace std; struct A { constexpr static std::string_view name = "A"; }; struct B { constexpr static std::string_view name = "B"; }; struct C {}; template<typename T> concept ObjectWithName = requires (T t) { {t.name} -> std::convertible_to<std::string_view>; }; #define CONCEPT_CONSTRAINED_TYPE(Name, Constraint) \ struct Name \ { \ \ template<typename... T> \ static constexpr bool Validate() \ { \ return false; \ } \ \ template<typename... T> \ requires requires (T... t) {requires (Constraint<T> && ...);} \ static constexpr bool Validate() \ { \ return true; \ } \ }; \ CONCEPT_CONSTRAINED_TYPE(Named, ObjectWithName); using Vars = std::variant<A,B,C>; template<typename Constr, typename... Arg> struct ConstrVar { static_assert(Constr::template Validate<Arg...>(), "Input arguments violate specified constraint"); std::variant<Arg...> variant; ConstrVar() = default; template<typename T> ConstrVar(T arg) { this->template operator=(arg); }; template<typename T> ConstrVar& operator=(T arg) { ConstrVar::ValidateArgument<T>(); variant = arg; return *this; } template<typename T> T Get() { return std::get<T>(variant); } template<size_t I> auto Get() { return std::get<I>(variant); } template<typename Visitor> auto Visit(Visitor visitor) { return std::visit(visitor, variant); } private: template<typename T> constexpr static void ValidateArgument() { static_assert(Constr::template Validate<T>(), "Constructor argument violate constraint"); static_assert((std::is_same_v<T, Arg> || ...), "Constructor argument type is not in Arg..."); } }; using NamedVar = ConstrVar<Named, A, B>; int main() { std::vector<NamedVar> named; named.push_back(A()); named.push_back(B()); named.push_back(B()); named.push_back(A()); for (auto&& val : named) { cout << val.Visit([](const auto& value){return value.name;}) << endl; } }