2015-03-30 5 views
7

Ho un tipo di tratto che controlla se un determinato tipo è un'istanza di un determinato modello di classe:Unificare tipo e non di tipo parametri di modello

template <template <typename...> class C, typename T> 
struct check_is_instance_of : std::false_type { }; 

template <template <typename...> class C, typename ...Ts> 
struct check_is_instance_of<C, C<Ts...>> : std::true_type { }; 

template <template <typename...> class C, typename T> 
struct is_instance_of : check_is_instance_of<C, std::remove_cv_t<T>> { }; 

Purtroppo, questo non funziona per i non-tipo parametri del modello in quanto non sono "catturati" dai parametri del modello variadic, così

is_instance_of<std::integral_constant, std::true_type> 

produce una fase di compilazione errore. Esiste un modo per scrivere un'implementazione di is_instance_of che funzioni per un numero arbitrario di parametri modello tipo e non tipo?

+0

una risposta alla tua domanda, ma questa implementazione non funzionerà con alias modello di modello. Forse questo è quello che vuoi, ma forse no. – TartanLlama

risposta

1

Non penso che ci sia un modo pulito per fare questo a meno che gli argomenti non di tipo siano tutti dello stesso tipo e tu sai quale tipo sia. In questo caso molto specifico, è possibile utilizzare l'overloading delle funzioni.

In qualsiasi altro caso, si finisce in una versione argomento modello del problema di inoltro perfetto in cui si dovrebbe specializzarsi per ogni combinazione di argomenti tipo/non tipo.

Se è necessario solo affrontare argomenti omogenei non di modello e si può indovinare il tipo, il seguente dovrebbe funzionare. È possibile sovraccaricare instance_of per diversi tipi (solo int è coperto qui), ma ci si deve creare esplicitamente un'istanza per ogni tipo si vuole essere in grado di gestire:

// variation for non-type parameters, only for uniform parameters with 
// known type. 
template <typename V, template <V...> class C, typename T> 
struct check_is_instance_of_nontype : std::false_type { }; 

template <typename V, template <V...> class C, V... Values> 
struct check_is_instance_of_nontype<V, C, C<Values...>> : std::true_type { }; 

// this is as in your example 
template <template <typename...> class C, typename T> 
struct check_is_instance_of : std::false_type { }; 

template <template <typename...> class C, typename ...Ts> 
struct check_is_instance_of<C, C<Ts...>> : std::true_type { }; 

template <template <typename...> class C, typename T> 
struct is_instance_of : check_is_instance_of<C, std::remove_cv_t<T>> { }; 

template <template <typename...> class C, typename T> 
constexpr bool instance_of() 
{ 
    return is_instance_of< C, T>::value; 
} 

template <template <int...> class C, typename T> 
constexpr bool instance_of() 
{ 
    return check_is_instance_of_nontype< int, C, T>::value; 
} 

template<int...> 
struct Duck 
{ 
}; 

template<typename A, typename B> 
struct Swallow 
{ 

}; 

int main() { 
    typedef Duck<1, 2> SittingDuck; 
    typedef Swallow< int, int> UnladenSwallow; 

    std::cout << instance_of< Duck, SittingDuck>() << instance_of< Swallow, UnladenSwallow>(); 
    return 0; 
} 
Non