// enum class Fruit{ Unknown, Apple, Banana, Orange, }; // string fruitStr = toString(Fruit::Orange); // Fruit fruit = stringTo<Fruit>(fruitStr);
// template<typename> struct TypeHolder {}; // ContainerType const& viewMapOf(TypeHolder<Fruits>);
template<typename SourceT, typename VariantsT> struct ViewMap { // using SourceType = SourceT ; // struct View: VariantsT { View(SourceT id=SourceT(), VariantsT vnt=VariantsT()): VariantsT(vnt), origin(id) { ;; } bool operator<(View const& b) const { return origin < b.origin ; } SourceT origin ; //< }; using Views = std::set<View> ; ViewMap() { ;; } ViewMap(std::initializer_list<View> const& initViews, View const& initInvalidView): views(initViews), invalidView(initInvalidView) { ;; } // static SourceT extractOrigin(View const& view) { return view.origin ; } Views views; // View invalidView; // } ;
struct StringVariant { StringVariant(std::string const& s = ""): str(s) { ;; } std::string str ; }; // template< typename SourceT > struct StringViewMap: ViewMap<SourceT,StringVariant> { using Base = ViewMap<SourceT, StringVariant>; using View = typename Base::View; StringViewMap() { ;; } StringViewMap(std::initializer_list<View> const& mapInit, View const& invalidInit): Base(mapInit,invalidInit) { ;; } // static std::string const& extractString(typename Base::View const& view) { return view.str ; } } ;
template<typename SourceType> string toString(SourceType id) { using MapRef = typename ViewMapTraits<SourceType>::MapRef; using PureMap = typename ViewMapTraits<SourceType>::PureMap; MapRef map = viewMapOf(TypeHolder<SourceType>()) ; auto const& views = map.views ; auto pos = views.find(typename PureMap::View(id)) ; return PureMap::extractString( (pos != views.end()) ? *pos : map.invalidView ) ; } template<typename SourceType> SourceType stringTo( string const& str ) { using MapRef = typename ViewMapTraits<SourceType>::MapRef; using PureMap = typename ViewMapTraits<SourceType>::PureMap; MapRef map = viewMapOf(TypeHolder<SourceType>()) ; auto const& views = map.views ; auto pos = std::find_if( views.begin(), views.end(), [&](typename PureMap::View const& val) { return PureMap::extractString(val) == str ; } ) ; return PureMap::extractOrigin( (pos != views.end()) ? *pos : map.invalidView ) ; }
template<typename SourceType> struct ViewMapTraits { using MapRef = decltype( mapViewOf(TypeHolder<SourceType>()) ) ; using PureMap = typename std::remove_cv<typename std::remove_reference<MapRef>::type>::type ; };
StringViewMap<Fruit> const& viewMapOf(TypeHolder<Fruit>) { static StringViewMap<Fruit> viewMap = { { {Fruit::Apple, {"apple"}}, {Fruit::Banana, {"banana"}}, {Fruit::Orange, {"orange"}}, }, {Fruit::Unknown, {"unknown"}} }; return viewMap ; }
enum class Mix { Unknown, RedApple, GreenApple, GreenBanana, BigOrange, SmallOrange, }; // Mix struct MixVariant { MixVariant(Fruit f = Fruit::Unknown, std::string const& s = ""): fruit(f), str(s) { ;; } Fruit fruit ; // std::string str ; // }; // struct MixViewMap: ViewMap<Mix,MixVariant> { using Base = ViewMap<Mix,MixVariant>; using View = typename Base::View; MixViewMap() { ;; } MixViewMap(std::initializer_list<View> const& mapInit, View const& invalidInit): Base(mapInit,invalidInit) { ;; } // toString, stringTo static std::string const& extractString(typename Base::View const& view) { return view.str ; } // toFruit static std::string const& extractFruit(typename Base::View const& view) { return view.fruit ; } } ; // MixViewMap const& viewMapOf(TypeHolder<Mix>) { static MixViewMap map = { { {Mix::RedApple, {Fruit::Apple, "red_apple"}}, {Mix::GreenApple, {Fruit::Apple, "green_apple"}}, {Mix::GreenBanana, {Fruit::Banana, "green_banana"}}, {Mix::BigOrange, {Fruit::Orange, "big_orange"}}, {Mix::SmallOrange, {Fruit::Orange, "small_orange"}}, }, {Mix::Unknown, {Fruit::Unknown, "unknown"}}, }; return map ; } // template<typename SourceType> Fruit toFruit(SourceType id) { using MapRef = typename ViewMapTraits<SourceType>::MapRef; using PureMap = typename ViewMapTraits<SourceType>::PureMap; MapRef map = viewMapOf(TypeHolder<SourceType>()) ; auto const& views = map.views ; auto pos = views.find(typename PureMap::View(id)) ; return PureMap::extractFruit( (pos != views.end()) ? *pos : map.invalidView ) ; }
string redAppleStr = "red_apple"; Mix mix = stringTo<Mix>(redAppleStr); // mix == Mix::RedApple Fruit mixFruit = toFruit(mix); // mixFruit == Fruit::Apple string mixFruitStr = toString(mixFruit); // mixFruitStr == "apple"
Source: https://habr.com/ru/post/238077/