Facendo un static_assert che un tipo di modello è un altro modello

Come faccio static_assert questo modo? Forse Boost lo supporta se non C ++ o nuove funzionalità in C ++ 11?

 template struct foo {}; template struct bar { static_assert(FooType is indeed foo for some T,"failure"); //how? }; 

Potresti fare qualcosa in questo modo. Dato un tratto che può verificare se una class è un’istanza di un modello di class:

 #include  template class TT> struct is_instantiation_of : std::false_type { }; template class TT> struct is_instantiation_of, TT> : std::true_type { }; 

Usalo come segue nel tuo programma:

 template struct foo {}; template struct bar { static_assert(is_instantiation_of::value, "failure"); }; int main() { bar b; // ERROR! bar> b; // OK! } 

Se lo desideri, puoi generalizzare questo per rilevare se una class è un’istanza di un modello con un numero qualsiasi di parametri (tipo), ad esempio:

 #include  template class TT, typename T> struct is_instantiation_of : std::false_type { }; template class TT, typename... Ts> struct is_instantiation_of> : std::true_type { }; template struct bar { static_assert(is_instantiation_of::value, "failure"); }; 

Dovresti quindi utilizzarlo in questo modo nel tuo programma:

 template struct bar { static_assert(is_instantiation_of::value, "failure"); }; int main() { bar b; // ERROR! bar> b; // OK! } 

Ecco un esempio dal vivo .

Come qualcun altro ha scritto,

 template class TT> struct is_specialization_of : std::false_type { }; template class TT, typename... Ts> struct is_specialization_of, TT> : std::true_type { }; 

Tuttavia, fai attenzione che questo funziona solo per le classi template i cui parametri template sono tutti nomi di tipi! Presentato con

 typedef std::array MyArray; static_assert(is_specialization_of::value, ""); 

semplicemente non riuscirà a compilare affatto.

Credo che C ++ 11 / C ++ 14 / C ++ 17 non abbia attualmente modo di gestire questa limitazione.

Alcuni piccoli miglioramenti rispetto alle altre risposte:

  • il nome ha effettivamente senso per quanto riguarda l’ordine dei parametri
  • gestisce correttamente i tipi const , volatile e di riferimento tramite std :: decay
  • implementa la variabile constexpr C ++ 14-style
  • accetta un numero arbitrario di tipi da testare (test per TUTTI)

Non ho intenzionalmente messo lo std :: decay_t su is_template_for_v perché un carattere type dovrebbe funzionare in modo identico indipendentemente dal fatto che sia chiamato con il suffisso _v o meno.

Ciò richiede C ++ 17 per std::conjunction , ma è ansible rimuovere la funzionalità variadic o implementare la propria conjunction usando c ++ 11/14.

 template class tmpl, typename T> struct _is_template_for : public std::false_type {}; template class tmpl, class... Args> struct _is_template_for> : public std::true_type {}; template class tmpl, typename... Ts> using is_template_for = std::conjunction<_is_template_for>...>; template class tmpl, typename... Ts> constexpr bool is_template_for_v = is_template_for::value; 

Uso:

 static_assert(is_template_for_v>); // doesn't fire