Der Versuch, sich auf die Gültigkeit der Arraygröße zu spezialisieren:
// base template
template<int p, typename T = void>
struct absolute {
operator int () const { return 0; }
};
// positive case template
template<int p>
struct absolute<p, typename std::void_t<int[p]>> {
operator int () const { return p; }
};
// negative case template
template<int p>
struct absolute<p, typename std::void_t<int[-p]>> {
operator int () const { return -p; }
};
int main() {
std::cout << absolute<5>() << std::endl;
std::cout << absolute<-5>() << std::endl;
std::cout << absolute<0>() << std::endl;
}
Fehler 1:
Der obige Code funktioniert gut mit gcc, kann jedoch nicht mit clang kompiliert werden .
Clang erzeugt den Fehler: Neudefinition der Vorlagenstruktur 'absolut'
Wer hat Recht?
Problem Nr. 2:
Sowohl mit gcc als auch mit clang (wenn wir die negative Spezialisierung entfernen, um clang wieder ins Spiel zu bringen), ist nicht klar, warum absolute<0>()
die Basisvorlage ausgewählt wird. Es ist nichts falsch mit int[0]
als auch mit std::void_t<int[0]>
denen scheint mehr spezialisiert zu werden:
// base template
template<int p, typename T = void>
struct absolute {
operator int () const { return -1; }
};
// positive case template
template<int p>
struct absolute<p, typename std::void_t<int[p]>> {
operator int () const { return p; }
};
int main() {
std::cout << absolute<5>() << std::endl; // 5
std::cout << absolute<0>() << std::endl; // -1, why not 0?
}
Und ... wenn die Basisvorlage nur ohne Implementierung deklariert wird, als:
// base template
template<int p, typename T = void>
struct absolute;
Sowohl gcc als auch clang konnten nicht kompiliert werden und beschwerten sich über die ungültige Verwendung eines unvollständigen Typs für den Aufruf : absolute<0>()
. Auch wenn es zum Spezialfall zu passen scheint.
Warum ist das so?
int[0]
ist durch den ISO C ++ Standard timsong-cpp.github.io/cppwp/n4659/dcl.array#1 verboten "sein Wert muss größer als Null sein"
template<int p> struct absolute<p, typename std::void_t<int[p]>>
undtemplate<int p> struct absolute
ist das nicht ein Duplikat?