c++ - Composing std::integral_constant values -
consider code
#include <iostream> #include <type_traits> enum thing {thing0, thing1, thing2, numthings}; enum object {object0, object1, object2, numobjects}; template <thing> struct thingvalue; template <> struct thingvalue<thing0> : std::integral_constant<int, 5> {}; template <> struct thingvalue<thing1> : std::integral_constant<int, 2> {}; template <> struct thingvalue<thing2> : std::integral_constant<int, 12> {}; template <object> struct objectvalue; template <> struct objectvalue<object0> : std::integral_constant<thing, thing2> {}; template <> struct objectvalue<object1> : std::integral_constant<thing, thing0> {}; template <> struct objectvalue<object2> : std::integral_constant<thing, thing1> {}; int main() { std::cout << thingvalue<objectvalue<object0>::value>::value << '\n'; // 12 }
i'm trying define, composevalues<t, value, pack...>
above in main() can written composevalues<object, object0, thingvalue, objectvalue>::value
. can extended number of such compositions. not absolutely vital thing do, i'd figure nice little exercise define such thing. i'm having difficulty syntax:
template <typename t, t value, template <typename> class...> struct composevalues; template <typename t, t value, template <typename> class first, template <typename> class... rest> struct composevalues<t, value, first, rest...> { static auto value = first<typename composevalues<t, value, rest...>::value>::value; }; template <typename t, t value, template <t> class last> struct composevalues<t, value, last> : std::integral_constant<t, last<value>::value> {}; // won't compile.
is possible i'm trying do?
the issue having can't mix template templates take different non-type arguments. in example, means objectvalue
, thingvalue
cannot bind template <typename> class...
.
a way fix encode enums in type kind of template can hold both of them indiscriminately. possible way treat enums int
s , let user worry passing in reasonable types.
first create wrappers around current types:
template <typename> struct thingvaluewrapper; template <int i> struct thingvaluewrapper<std::integral_constant<int,i>> : thingvalue<static_cast<thing>(i)> {}; template <typename> struct objectvaluewrapper; template <int i> struct objectvaluewrapper<std::integral_constant<int, i>> : objectvalue<static_cast<object>(i)> {};
then can pretty similar had:
template <typename t, t value, template <typename> class...> struct composevalues; template <typename t, t value, template <typename> class first, template <typename> class... rest> struct composevalues<t, value, first, rest...> : std::integral_constant<int, first<typename composevalues<t, value, rest...>::type>::value> {}; template <typename t, t value> struct composevalues<t, value> : std::integral_constant<int, static_cast<int>(value)> {};
the difference original use-case need use our wrappers instead of original enum traits:
composevalues<object, object0, thingvaluewrapper, objectvaluewrapper>::value
Comments
Post a Comment