Reputation: 15327
Is there a standard way for me to select a type at compile-time on an unsigned index in c++11?
For example, something like:
using type_0 = static_switch<0, T, U>; // yields type T
using type_1 = static_switch<1, T, U>; // yields type U
If there is a variadic-template version, it would be very useful.
Upvotes: 39
Views: 8151
Reputation: 22552
You could probably use a boost::mpl::vector
to store your types and use boost::mpl::at<v, n>::type
to get a type with from the index.
template<std::size_t N, typename... T>
using static_switch = typename boost::mpl::at<boost::mpl::vector<T...>, N>::type;
Upvotes: 10
Reputation: 4207
How about
template<size_t N, typename T, typename U>
struct static_switch {};
template<typename T, typename U>
struct static_switch<0, T, U>{typedef T type;};
template<typename T, typename U>
struct static_switch<1, T, U>{typedef U type;};
You would use it as follows:
using type_0 = static_switch<0, T, U>::type; // yields type T
using type_1 = static_switch<1, T, U>::type; // yields type U
This is more or less implemented for you in std::conditional.
Upvotes: 9
Reputation: 27028
With C++17 you can also go about this another way. Instead of calculating the type explicitly you can use constexpr if
and do different things (including returning different types) directly:
template<size_t N>
decltype(auto) foo() {
if constexpr(N % 2 == 0) {
return std::string("Hello I'm even");
} else {
return std::pair(
std::vector<char>{ 'O', 'd', 'd', ' ', 'v', 'a', 'l', 'u', 'e' },
[](){ return N; });
}
}
foo<0>() // "Hello I'm even"
foo<21>().second() // 21
You can also use this to get just the type:
using type_0 = decltype(foo<0>());
using type_1 = decltype(foo<1>());
Upvotes: 2
Reputation: 53047
This should work:
template<std::size_t N, typename... T>
using static_switch = typename std::tuple_element<N, std::tuple<T...> >::type;
Another method:
template<std::size_t N, typename T, typename... Ts>
struct static_switch {
using type = typename static_switch<N - 1, Ts...>::type;
};
template<typename T, typename... Ts>
struct static_switch<0, T, Ts...> {
using type = T;
};
Upvotes: 51