betrachten den CodeC++ Fehlerunterscheidungs Spezialisierung wenn eine const Array vorbei
template <class A>
class B;
template <class A>
class B<const A>{};
template <class A, int N>
class B<A[N]>{};
template <class A>
class B<A*>{};
template <class A>
class B<A&>{};
die folgende Vorlage Instanziierungen funktionieren:
A<int*&>
A<const int*>
A<int*[3]>
aber das folgende nicht funktioniert:
A<const int[3]>
Gibt es einen Grund, dass diese bestimmte Kombination ungültig ist oder ist es vielleicht ein Fehler mit g ++ 4.6 .3?
Übrigens habe ich das mit SFINAE und boost :: disable_if <> umgehen können, so dass zumindest das Problem gelöst ist.
EDIT
habe ich vergessen, dass der Fehler in Frage zu erwähnen ist eine zweideutige Klasse Template-Instantiierung und es konnte nicht zwischen der Überlastung für const oder die Überlastung für eine Anordnung entscheiden.
EDIT2
Das hat nichts mit Zeigern zu tun hat, ist hier der volle Kontext:
Ich C++ Metaprogrammierung durch das Buch gehen und tue Frage 2-3 (Kapitel 2 Frage 3), die besagt:
Verwenden Sie die Typ Traits-Einrichtungen, um eine type_descriptor Klassenvorlage zu implementieren, deren Instanzen, wenn gestreamt, den Typ ihrer Vorlage Parameter: Hinweis: Wir können nicht verwenden RTTI mit dem gleichen Effekt, da nach 18.5.1 [lib.type.info], Absatz 7 des Standards, typeid (T) .name() nicht garantiert ein aussagekräftiges Ergebnis liefert.
Meine Lösung (einschließlich der Abhilfe für das Fehler compilation) ist wie folgt:
//QUESTION 2-3
template <class T, class enable = void>
struct type_descriptor
{
std::string operator()() const
{
return "Unknown";
}
};
//specializations for primitive types
#define TYPE_DESC_SPEC(type) template <> \
struct type_descriptor<type,void> \
{std::string operator()() const{return #type;}};
TYPE_DESC_SPEC(int)
TYPE_DESC_SPEC(long)
TYPE_DESC_SPEC(void)
TYPE_DESC_SPEC(short)
TYPE_DESC_SPEC(unsigned char)
TYPE_DESC_SPEC(unsigned short)
TYPE_DESC_SPEC(unsigned long)
//specializations for modifiers *, const, &, and [N]
template <class T>
struct type_descriptor<T&,void>
{std::string operator()(){return type_descriptor<T>()() + " &";}};
template <class T>
struct type_descriptor<T*,void>
{std::string operator()(){return type_descriptor<T>()() + " *";}};
//Replace void with what's in the comment for the workaround.
template <class T>
struct type_descriptor<const T, void/*typename boost::disable_if<boost::is_array<T> >::type*/>
{std::string operator()(){return type_descriptor<T>()() + " const";}};
template <class T>
struct type_descriptor<T(*)(),void>
{std::string operator()(){return type_descriptor<T>()() + " (*)()";}};
template <class T, class U>
struct type_descriptor<T(*)(U),void>
{std::string operator()(){return type_descriptor<T>()() + " (*)(" + type_descriptor<U>()() + ")";}};
template <class T, int N>
struct type_descriptor<T[N],void>
{
std::string operator()()
{
std::stringstream s;
s << type_descriptor<T>()() << " [" << N << "]";
return s.str();
}
};
template <class T>
struct type_descriptor<T[],void>
{std::string operator()(){return type_descriptor<T>()() + " []";}};
//Now overload operator<< to allow streaming of this class directly
template <class T>
std::ostream & operator<<(std::ostream & s, type_descriptor<T> t)
{
return s << t();
}
//END QUESTION 2-3
Verwendungsbeispiel ist:
std::cout << "\nQuestion 2-3 results\n";
std::cout << type_descriptor<int*>() << std::endl;
std::cout << type_descriptor<int*[3]>() << std::endl;
std::cout << type_descriptor<std::string*>() << std::endl;
std::cout << type_descriptor<const int&>() << std::endl;
std::cout << type_descriptor<const int *const&>() << std::endl;
std::cout << type_descriptor<int[4]>() << std::endl;
std::cout << type_descriptor<int(*)()>() << std::endl;
std::cout << type_descriptor<int*&(*)(const char &)>() << std::endl;
std::cout << type_descriptor<int*&>() << std::endl;
std::cout << type_descriptor<int[]>() << std::endl;
std::cout << type_descriptor<const long[]>() << std::endl;
und der entsprechende Ausgang ist (wenn die Umgehung in ist, andernfalls kompiliert es nicht auf der letzten):
int * int * [3] Unknown * int const & int const * const & int [4] int (*)() int * & (*)(Unknown const &) int * & int [] long const []
So C++ kann anders iate Zeiger und Arrays für die Template-Parameter, ist in der Lage, korrekt und rekursiv Compound-Typen zu trennen und das korrekte Ergebnis auszugeben, mit Ausnahme von const A[]
. Dazu braucht es Hilfe
Gehen Sie zu raten - aber ich denke 'const int [3]' zerfällt in 'const int *' –
@AdrianCornish nein, das ist es nicht, siehe die Bearbeitung. Abgesehen davon, wenn das das dritte gültige Beispiel wäre, sollte ich auch nicht funktionieren. – SirGuy
3. würde funktionieren, weil 'const int *' anders ist als 'int *' - versuchen (erfolglos), den Abschnitt des Standards zu finden, der den Zerfall dokumentiert ;-) –