Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
//твое перечисление
enum class MyEnum
{
One,
Two,
Three
//etc
};
//соответствующие перечислению строки
char OneStr[] = "One";
char TwoStr[] = "Two";
char ThreeStr[] = "Three";
//etc
template <typename T, T t>
struct ValueToType {}; //смотри Александреску
template <MyEnum ParamEnum, typename Param, Param Val>
class MyPair
{
public:
//опять же, по поводу параметров этих функций, смотри Александреску
MyEnum toEnum(ValueToType<Param, Val> const&) { return ParamEnum; }
Param toParam(ValueToType<MyEnum, ParamEnum> const&) { return Val; }
};
template <class ... T>
class MyEnumDecoder {}; //базовый шаблон, который мы "раскрутим" специализацией
template <MyEnum ParamEnum, typename Param, Param Val, class ... T>
class MyEnumDecoder<MyPair<ParamEnum, Param, Val>, T ...> :
protected MyPair<ParamEnum, Param, Val>, protected MyEnumDecoder<T ...>
{
private:
using MyPair<ParamEnum, Param, Val>::toEnum;
using MyPair<ParamEnum, Param, Val>::toParam;
using MyEnumDecoder<T ...>::toEnum;
using MyEnumDecoder<T ...>::toParam;
public:
MyEnumDecoder(MyPair<ParamEnum, Param, Val> mp, T ... others) :
MyPair<ParamEnum, Param, Val>(mp), MyEnumDecoder<T ...>(others ...) {}
template <Param param>
MyEnum toEnum()
{
return this->toEnum(ValueToType<Param, param>());
}
template <MyEnum paramEnum>
Param toParam()
{
return this->toParam(ValueToType<MyEnum, paramEnum>());
}
};
//это замыкание рекурсии. чтобы понять, что происходит выше, смотри что происходит тут
template <MyEnum ParamEnum, typename Param, Param Val>
class MyEnumDecoder<MyPair<ParamEnum, Param, Val>> :
protected MyPair<ParamEnum, Param, Val>
{
private:
using MyPair<ParamEnum, Param, Val>::toEnum;
using MyPair<ParamEnum, Param, Val>::toParam;
public:
MyEnumDecoder(MyPair<ParamEnum, Param, Val> mp) :
MyPair<ParamEnum, Param, Val>(mp) {}
template <Param param>
MyEnum toEnum()
{
return this->toEnum(ValueToType<Param, param>());
}
template <MyEnum paramEnum>
Param toParam()
{
return this->toParam(ValueToType<MyEnum, paramEnum>());
}
};
/*************************************************************************************/
int _tmain(int argc, _TCHAR* argv[])
{
MyPair<MyEnum::One, char*, OneStr> mpOne;
MyPair<MyEnum::Two, char*, TwoStr> mpTwo;
MyPair<MyEnum::Three, char*, ThreeStr> mpThree;
MyEnumDecoder<
MyPair<MyEnum::One, char*, OneStr>,
MyPair<MyEnum::Two, char*, TwoStr>,
MyPair<MyEnum::Three, char*, ThreeStr>
> mp(mpOne, mpTwo, mpThree);
MyEnum me = mp.toEnum<OneStr>();
char* str = mp.toParam<MyEnum::Three>();
getchar();
return 0;
}
const char* value = "one";
MyEnum me = mp.toEnum<value>();
char* str = mp.toParam<me>();
char* str = mp.toParam<me>();
еще на этапе компиляции, а MyEnum me = mp.toEnum<value>();
будет всегда рантайм проверка.char* str = mp.toParam<me>();
char* str = mp.toParam<MyEnum::One>();
template<class Tag, class Type>
struct TagValue{
using tag = Tag;
using type = Type;
Type value;
TagValue(Type &value) : value(value){}
TagValue(Type &&value) : value(forward<Type>(value) ){}
};
template<class Tag, class Type>
using tv = TagValue<Tag, Type>; // сокращенная запись
// type autodetect
/// call this to auto deduce &/&&
template<typename _tag, typename T>
TagValue<_tag, T> mtv(T &&value){
return TagValue<_tag, T>( std::forward<T>(value) );
}
namespace tags{
class three;
}
using namespace tags;
auto list = make_tuple(
tv<class one, int>(1) ,
mtv<class two>(2), // либо
mtv<three>(3) // либо (если class three уже используется, можно не объявлять в namespace tags)
)
int num2 = tuple_get_tag<class two>(list);
int num3 = tuple_get_tag<three>(list);
С одной стороны, хочется читаемых конфигов, с другой — быстрого парсинга и быстрого обращения по этому типу.
String enum — строковые enum