2013-03-14 10 views
35

Esiste un modo standard per selezionare un tipo in in fase di compilazione in un indice senza segno in C++ 11?Come posso cambiare/selezionare i tipi durante la compilazione?

Per esempio, qualcosa come:

using type_0 = static_switch<0,T,U>; // yields type T 
using type_1 = static_switch<1,T,U>; // yields type U 

Se c'è una versione variadic-template, sarebbe molto utile.

risposta

42

Questo dovrebbe funzionare:

template<std::size_t N, typename... T> 
using static_switch = typename std::tuple_element<N, std::tuple<T...> >::type; 

Un altro metodo:

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; 
}; 
+1

+1 eccezionale risposta . Sono sempre interessato a nuovi modi di utilizzare modelli variadici. Grazie per un altro – WhozCraig

+0

+1 Non sapevo che si potesse avere un 'utilizzo di modelli. –

+1

@AlexChamberlain non tutti i compilatori supportano (lo fanno, sono le loro ultime versioni) –

10

Si potrebbe forse usare un boost::mpl::vector per memorizzare i tipi e utilizzare boost::mpl::at<v,n>::type per ottenere un tipo con dall'indice.

template<std::size_t N, typename... T> 
using static_switch = typename boost::mpl::at<boost::mpl::vector<T...>, N>::type; 
8

Come su

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;}; 

Si potrebbe usare come segue:

using type_0 = static_switch<0,T,U>::type; // yields type T 
using type_1 = static_switch<1,T,U>::type; // yields type U 

Questo è più o meno implementato per voi in std::conditional.

+8

Nota: 'std :: condizionale' è ottimo se ci sono solo 2 alternative. Dato che l'OP sta parlando di un indice, potrebbero essercene di più. –

1

Con C++ 17 puoi anche andare in un altro modo. Invece di calcolare il tipo in modo esplicito è possibile utilizzare constexpr if e fare cose diverse (tra cui il ritorno tipi diversi) direttamente:

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 

È inoltre possibile utilizzare questo per ottenere solo il tipo:

using type_0 = decltype(foo<0>()); 
using type_1 = decltype(foo<1>()); 
Problemi correlati