Ich weiß, es trivial ist zu prüfen, ob ein Typ eine Instanz einer Klasse-Vorlage ist unter TYPE Parametern, wie hier erklärt: How can I check if a type is an instantiation of a given class template?C++ 11: Wie überprüft man, ob ein Typ eine Instanziierung einer gegebenen Klassenvorlage von "heterogenen" NON-TYPE Parametern ist?
Aber ... ist es möglich, ein variadische „is_instantiation_of__ntp < zu haben .. > "(NTP steht für Non-Type Params), die Vorlagen mit einer beliebigen Anzahl von heterogenenNON-TYPE Parametern akzeptieren würde? Zum Beispiel:
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'>;
Und in der Lage sein, es zu benutzen, wie folgt:
is_instantiation_of__ntp<char*, bool, long, size_t, char, many_hetero_nontype_params_example, ManyHeteroNontypeParamsEx>::value
Ich weiß, das kann leicht für NON-TYPE Parameterlisten implementiert wird, die 1) „homogen“ sind (Werte des gleichen Typ), oder 2) einige Parameter (so dass eine nicht variadische Lösung praktikabel ist). Ich schrieb sogar einen Testfall diese Sonderfälle (kompiliert mit gcc 4.7.0) zeigt eine bessere Vorstellung davon zu geben, was ich spreche:
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;
}
}
}
Wie erwartet, die Ausgabe, die Sie erhalten, ist:
[TypeParamsEx] specializes [type_params_example]
[HomeogenousNonTypeParamsEx] specializes [homogeneous_nontype_params_example]
[FixedCountNonTypeParamsEx] specializes [fixedcount_nontype_params_example]
Das Problem ist keine dieser Vorlagen arbeiten für die many_hetero_nontype_params_example (oben). Beispiel: ein einzelnes variadisches "is_instantiation_of__ntp", das Vorlagen mit einer beliebigen Anzahl von heterogenen Nicht-Typ-Parametern akzeptiert.
Ich denke, wenn Primär-Vorlagen nicht benötigt wurden, um Parameter-Packs am Ende der Template-Parameterliste zu haben, dann wäre dies einfach zu implementieren. Oder wenn es möglich wäre, einen Wrapper-Struct/Nested-Struct-Ansatz zu verwenden. Hier sind meine (nicht) Versuche:
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;
//}
}
}
...
Ist eine variadische Lösung für diese überhaupt möglich?
Vielen Dank im Voraus.
Ich glaube, ich habe Ihre Frage in meiner ursprünglichen Antwort missverstanden, tut mir leid. Löscht es und liefert eine bessere Antwort. –
Ihre ursprüngliche Antwort erklärte, warum es keine offensichtliche Lösung für dieses Problem gibt, wie zum Beispiel die Deklaration eines Parameterpakets "typename ... ScalarTypes", um dann die Vorlagenvorlage "Vorlage Klasse TheTemplate" zu deklarieren Parameterliste. Andere mögliche Lösungen werden nicht behandelt, z. B. der Versuch is_instantiation_of__nontypes_v2__, den ich gepostet habe, der eine umschließende Struktur zum Deklarieren des Parameter-Packs für den Template-Template-Parameter verwendet, der in der Parameterliste der geschachtelten Struktur deklariert ist. –
etherice
Wenn Sie erklärt hätten, warum dieser "v2" -Versuch nicht funktioniert (speziell die gcc-Fehler beim Versuch, ihn zu benutzen), wäre ich ziemlich überzeugt, dass dies nicht möglich ist und die Antwort akzeptiert hätte. Aber es wäre schön, das sicher zu wissen. Danke, dass du dir das angeschaut hast. – etherice