Jest to technika czasami używać podczas nadrzędnymi template
funkcje, które idzie tak:Puste pakiety zmienne wyliczeń - czy czynią dwie funkcje różnymi?
#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>();
}
To odróżnia do_stuff
z do_stuff
, ponieważ weźmie 0 lub więcej UniqueEnum<1>
s, a druga zajmuje 0 lub więcej UniqueEnum<-1>
s. gcc 4.8 uważa te różne puste pakiety za odrębne.
Jednak w najnowszej wersji języka próbowałem, to się nie udaje: traktuje funkcję z 0 UniqueEnum<1>
s jako taką samą jak funkcja z 0 UniqueEnum<-1>
s.
Istnieją proste obejścia, które działają w szczęściu, ale zastanawiam się, czy moja powyższa technika jest zgodna z prawem - czy dwie funkcje różnią się tylko pustymi pakietami parametrów o różnych parametrach?
Czy ma to zastosowanie tylko wtedy, gdy wyraźnie podamy argument, a nie wywnioskujemy? (Czy, gdybym uczynił funkcję wziąć 'T const &', a następnie przeszedłbym '7', czy sztuczka nie byłaby już legalna?) – Yakk
@Yakk: W takim przypadku nie jestem do końca pewien, ale przeczytałem przez cały 14.8.2 kilka razy i wydaje mi się, że Standard nie określa, jakie zachowanie powinno być –