so che è banale per verificare se un tipo è un'istanza di una classe template prendendo TIPO parametri, come spiegato qui: How can I check if a type is an instantiation of a given class template?C++ 11: Come verificare se un tipo è un'istanza di un dato modello di classe di parametri "eterogenei" NON TIPO?
Ma ... è possibile avere una variadic "is_instantiation_of__ntp < .. .> "(NTP per non tipo Params) che accetta i modelli con un numero qualsiasi di eterogeneoparametri NON-TYPE? Per esempio:
template<char*, bool, long, size_t, char>
struct many_hetero_nontype_params_example {};
char HELLO_WORLD[] = "hello world";
using ManyHeteroNontypeParamsEx = many_hetero_nontype_params_example<HELLO_WORLD, false, -16, 777, 'x'>;
ed essere in grado di usarlo come segue:
is_instantiation_of__ntp<char*, bool, long, size_t, char, many_hetero_nontype_params_example, ManyHeteroNontypeParamsEx>::value
So che questo può essere implementato facilmente per elenchi di parametri NON-tipo che sono 1) "omogenei" (valori dello stesso tipo), o 2) pochi parametri (tale che una soluzione non variabile sia pratica). Ho anche scritto un banco di prova che dimostrano questi casi particolari (compilato con GCC 4.7.0) per dare una migliore idea di cosa sto parlando:
namespace test__is_instantiation_of__
{
// is_instantiation_of
template< template<typename...> class Template, typename T >
struct is_instantiation_of : std::false_type {};
template< template<typename...> class Template, typename... Args >
struct is_instantiation_of< Template, Template<Args...> > : std::true_type {};
// is_instantiation_of__homogeneous_nontype_params__
template< typename NTP, template<NTP...> class Template, typename T >
struct is_instantiation_of__homogeneous_nontype_params__ : std::false_type {};
template< typename NTP, template<NTP...> class Template, NTP... Args >
struct is_instantiation_of__homogeneous_nontype_params__< NTP, Template, Template<Args...> > : std::true_type {};
// is_instantiation_of__fixedcount_nontype_params__
template< typename NTP1, typename NTP2, template<NTP1, NTP2> class Template, typename T >
struct is_instantiation_of__fixedcount_nontype_params__ : std::false_type {};
template< typename NTP1, typename NTP2, template<NTP1, NTP2> class Template, NTP1 v1, NTP2 v2 >
struct is_instantiation_of__fixedcount_nontype_params__< NTP1, NTP2, Template, Template<v1, v2> > : std::true_type {};
// type_params_example
template<typename T1, typename T2, typename T3>
struct type_params_example {};
// homogeneous_nontype_params_example
template<bool B1, bool B2, bool B3, bool B4>
struct homogeneous_nontype_params_example {};
// fixedcount_nontype_params_example
template<long L, char C>
struct fixedcount_nontype_params_example {};
using /*.........*/ TypeParamsEx = /*..........*/ type_params_example<std::string, std::tuple<long, void*>, double>;
using HomogenousNontypeParamsEx = homogeneous_nontype_params_example<true, false, true, false>;
using FixedCountNontypeParamsEx = fixedcount_nontype_params_example<777, 'x'>;
void run()
{
using std::cout;
using std::endl;
if (is_instantiation_of<type_params_example, TypeParamsEx>::value) {
cout << "[TypeParamsEx] specializes [type_params_example]" << endl;
}
if (is_instantiation_of<type_params_example, HomogenousNontypeParamsEx>::value) {
cout << "[HomogenousNontypeParamsEx] specializes [type_params_example]" << endl;
}
if (is_instantiation_of<type_params_example, FixedCountNontypeParamsEx>::value) {
cout << "[FixedCountNontypeParamsEx] specializes [type_params_example]" << endl;
}
if (is_instantiation_of__homogeneous_nontype_params__<bool, homogeneous_nontype_params_example, TypeParamsEx>::value) {
cout << "[TypeParamsEx] specializes [homogeneous_nontype_params_example]" << endl;
}
if (is_instantiation_of__homogeneous_nontype_params__<bool, homogeneous_nontype_params_example, HomogenousNontypeParamsEx>::value) {
cout << "[HomogenousNontypeParamsEx] specializes [homogeneous_nontype_params_example]" << endl;
}
if (is_instantiation_of__homogeneous_nontype_params__<bool, homogeneous_nontype_params_example, FixedCountNontypeParamsEx>::value) {
cout << "[FixedCountNontypeParamsEx] specializes [homogeneous_nontype_params_example]" << endl;
}
if (is_instantiation_of__fixedcount_nontype_params__<long, char, fixedcount_nontype_params_example, TypeParamsEx>::value) {
cout << "[TypeParamsEx] specializes [fixedcount_nontype_params_example]" << endl;
}
if (is_instantiation_of__fixedcount_nontype_params__<long, char, fixedcount_nontype_params_example, HomogenousNontypeParamsEx>::value) {
cout << "[HomogenousNontypeParamsEx] specializes [fixedcount_nontype_params_example]" << endl;
}
if (is_instantiation_of__fixedcount_nontype_params__<long, char, fixedcount_nontype_params_example, FixedCountNontypeParamsEx>::value) {
cout << "[FixedCountNontypeParamsEx] specializes [fixedcount_nontype_params_example]" << endl;
}
}
}
Come previsto, l'uscita si ottiene è:
[TypeParamsEx] specializes [type_params_example]
[HomeogenousNonTypeParamsEx] specializes [homogeneous_nontype_params_example]
[FixedCountNonTypeParamsEx] specializes [fixedcount_nontype_params_example]
Il problema è nessuno di quei modelli funziona per molti_hetero_nontype_params_example (sopra). I.e: un singolo, variadico "is_instantiation_of__ntp" che accetta i template con un numero qualsiasi di parametri non-tipo eterogenei.
Penso che se i modelli primari non avessero bisogno di avere i pacchetti di parametri alla fine dell'elenco dei parametri del modello, questo sarebbe facile da implementare. O se fosse possibile usare un approccio wrapper-struct/nested-struct. Qui sono i miei (non) tentativi:
namespace test__is_instantiation_of__nontypes__
{
template<char*, bool, long, size_t, char>
struct many_hetero_nontype_params_example {};
char HELLO_WORLD[] = "hello world";
using ManyHeteroNontypeParamsEx = many_hetero_nontype_params_example<HELLO_WORLD, false, -16, 777, 'x'>;
/*
* is_instantiation_of__nontypes_v1__ (version 1)
* if uncommented, syntax error as expected ...
* error: parameter pack 'NTPs' must be at the end of the template parameter list
* error: parameter pack argument 'NTPs ...' must be at the end of the template argument list
*/
//template< typename... NTPs, template<NTPs...> class Template, typename T >
//struct is_instantiation_of__nontypes_v1__ : std::true_type {};
//template< typename... NTPs, template<NTPs...> class Template, NTPs... NonTypeArgs >
//struct is_instantiation_of__nontypes_v1__< NTPs..., Template, Template<NonTypeArgs...> > : std::true_type {};
/*
* is_instantiation_of__nontypes_v2__ (version 2)
* no syntax error (but see instantiation errors below)
*/
template<typename... NTPs>
struct is_instantiation_of__nontypes_v2__
{
template< template<NTPs...> class Template, typename T >
struct impl : std::false_type {};
template< template<NTPs...> class Template, NTPs... NonTypeArgs >
struct impl< Template, Template<NonTypeArgs...> > : std::true_type {};
};
void run()
{
/*
* uncommented since "v1" template has syntax error, but this is how it would be used ...
*/
//if (is_instantiation_of__nontypes_v1__<char*, bool, long, size_t, char, many_hetero_nontype_params_example, ManyHeteroNontypeParamsEx>::value) {
// std::cout << "yes" << std::endl;
//}
/*
* "v2" template has no syntax error, but the following attempt to use it results in these errors ...
*
* error: type/value mismatch at argument 1 in template parameter list for 'template<class ... NTPs> template<template<template<NTPs ...<anonymous> > class Template, class T> template<class ... NTPs> template<NTPs ...<anonymous> > class Template, class T> struct is_instantiation_of__nontypes_v2__<NTPs>::impl'
* error: expected a template of type 'template<class ... NTPs> template<NTPs ...<anonymous> > class Template', got 'template<char* <anonymous>, bool <anonymous>, long int <anonymous>, long unsigned int <anonymous>, char <anonymous> > struct many_hetero_nontype_params_example'
*/
//if (is_instantiation_of__nontypes_v2__<char*, bool, long, size_t, char>::impl<many_hetero_nontype_params_example, ManyHeteroNontypeParamsEx>::value) {
// std::cout << "yes" << std::endl;
//}
}
}
...
è una soluzione variadic per questo anche possibile?
Grazie in anticipo.
Penso di aver frainteso la tua domanda nella mia risposta originale, mi dispiace. Lo eliminerà e fornirà una risposta migliore. –
La tua risposta originale ha spiegato perché non esiste una soluzione ovvia a questo problema, come dichiarare un pacchetto di parametri "typename ... ScalarTypes" per poi dichiarare il template template "template class TheTemplate" nello stesso parametro-list. Non copre altre possibili soluzioni, come il tentativo is_instantiation_of__nontypes_v2__ che ho postato, che utilizza una struct per dichiarare il parameter-pack per il parametro template-template dichiarato nella lista-parametri della struttura annidata. –
etherice
Se avessi potuto spiegare perché quel tentativo di "v2" non avrebbe funzionato (in particolare, gli errori di gcc sul tentativo di usarlo), sarei stato abbastanza convinto che questo non potesse essere fatto e avessi accettato la risposta. Ma sarebbe bello saperlo con certezza. Grazie per aver esaminato questo. – etherice