2013-07-24 17 views
6

Sto cercando di trovare il tipo A in un parametro confezione:trovare un tipo in una confezione parametro

template <int I, typename A, typename B, typename ...C> 
struct index_of 
{ 
    static constexpr int const value = 
    std::is_same<A, B>::value ? I : index_of<I + 1, A, C...>::value; 
}; 

template <int I, typename A, typename B> 
struct index_of<I, A, B> 
{ 
    static constexpr int const value = 
    std::is_same<A, B>::value ? I : -1; 
}; 

Questo sembra funzionare, ma sono in grado di eliminare il parametro non standardizzate I, che vorrei essere un parametro predefinito, ma non può renderlo tale, a causa del pacchetto di parametri alla fine. Come eliminare/nascondere I, quindi la metafunzione diventa più user-friendly?

risposta

3
template <typename A, typename B, typename... C> 
struct index_of 
{ 
    static constexpr int const value = 
    std::is_same<A, B>{} 
    ? 0 
    : (index_of<A, C...>::value >= 0) ? 1+index_of<A, C...>::value : -1; 
}; 

template <typename A, typename B> 
struct index_of<A, B> 
{ 
    static constexpr int const value = std::is_same<A, B>{} -1; 
}; 

Nota il std::is_same<A, B>{} -1 utilizza una conversione da bool a int.


Better by derivante da integral_constant:

template <typename A, typename B, typename... C> 
struct index_of 
    : std::integral_constant 
    < int, 
     std::is_same<A, B>{} 
     ? 0 
     : (index_of<A, C...>{} == -1 ? -1 : 1+index_of<A, C...>{}) 
    > 
{}; 

template <typename A, typename B> 
struct index_of<A, B> 
    : std::integral_constant < int, std::is_same<A, B>{} -1 > 
{}; 

Se non avete bisogno di tornare -1 nel caso in cui il tipo non si trova: (se qualcuno sa come incorporare un static_assert qui per un messaggio abbastanza diagnostico, apprezzerei un commento/modifica)

template <typename A, typename B, typename... C> 
struct index_of 
    : std::integral_constant < std::size_t, 
          std::is_same<A, B>{} ? 0 : 1+index_of<A, C...>{} > 
{}; 

template <typename A, typename B> 
struct index_of<A, B> 
    : std::integral_constant<std::size_t, 0> 
{ 
    constexpr operator std::size_t() const 
    { 
     return std::is_same<A, B>{} 
       ? 0 
       : throw std::invalid_argument("Type not found!"); 
    } 
}; 
+0

Ma il secondo e il terzo metafunzionamento non supportano correttamente i duplicati. – user1095108

+0

@ user1095108 Hai ragione, l'ho semplificato eccessivamente. Fisso. – dyp

6

È possibile nascondere questa implementazione in un namespace e utilizzare un'altra classe che chiama l'implementazione con un esempio di parametro predefinito:

namespace detail 
{ 
    // your code as it is in the question 
} 

template <typename A, typename... B> 
struct index_of 
{ 
    static int const value = detail::index_of<0, A, B...>::value; 
}; 

Modifica

Nel suo commento dyp suggerisce un modo più semplice per difetto I utilizzando un alias

template <typename A, typename... B> 
using index_of = detail::index_of<0, A, B...>; 
+2

In C++ 11, potresti persino usare un modello di alias. – dyp

Problemi correlati