Es gibt eine Technik, die ich manchmal verwenden, wenn template
Funktionen überschreiben, das so geht:Leere Variant Packs von Enums - machen sie zwei verschiedene Funktionen?
#include <utility>
template<int> struct unique_enum { enum class type {}; };
template<int index> using UniqueEnum = typename unique_enum<index>::type;
template<bool b, int index=1>
using EnableFuncIf = typename std::enable_if< b, UniqueEnum<index> >::type;
template<bool b, int index=1>
using DisableFuncIf = EnableFuncIf<!b, -index>;
// boring traits class:
template<typename T>
struct is_int : std::false_type {};
template<>
struct is_int<int> : std::true_type {};
#include <iostream>
// use empty variardic packs to give these two SFINAE functions different signatures:
template<typename C, EnableFuncIf< is_int<C>::value >...>
void do_stuff() {
std::cout << "int!\n";
}
template<typename C, DisableFuncIf< is_int<C>::value >...>
void do_stuff() {
std::cout << "not int!\n";
}
int main() {
do_stuff<int>();
do_stuff<double>();
}
Das unterscheidet do_stuff
von do_stuff
, denn man nimmt 0 oder mehr UniqueEnum<1>
s, und der andere nimmt 0 oder mehr UniqueEnum<-1>
s. gcc 4.8 betrachtet diese verschiedenen leeren Pakete als unterschiedlich.
Allerdings, in der neuesten Version von clang ich versuchte, dies schlägt fehl: Es behandelt die Funktion mit 0 UniqueEnum<1>
s als die gleiche Funktion wie die 0 UniqueEnum<-1>
s.
Es gibt einfache Problemumgehungen, die in clang funktionieren, aber ich frage mich, ob meine obige Technik legal ist - tun zwei Funktionen template
s, die sich nur durch leere variardic Parameterpakete unterscheiden, tatsächlich anders?
Gilt dies nur, wenn wir das Argument explizit angeben und es nicht ableiten? (Hätte ich die Funktion "T const &" nehmen lassen, dann "7" daran übergeben, wäre der Trick nicht mehr legal?) – Yakk
@Yakk: In diesem Fall bin ich mir nicht ganz sicher, aber ich habe gelesen durch die ganze 14.8.2 mehrere Male und es scheint mir der Standard nicht angibt, was das Verhalten sein sollte –