Przypuśćmy, że chcesz napisać rodzajowe funkcji void f<T>()
, który nie jedno czy T
jest rodzajem POD a co innego jeśli T
jest non-POD (lub jakiegokolwiek innego arbitralnego orzecznik).Tag wysyłka kontra metody statyczne na częściowo wyspecjalizowanych klas
Jednym ze sposobów osiągnięcia tego celu byłoby wykorzystanie wzoru tag wysyłki jak biblioteki standardowej robi z kategorii iterator:
template <bool> struct podness {};
typedef podness<true> pod_tag;
typedef podness<false> non_pod_tag;
template <typename T> void f2(T, pod_tag) { /* POD */ }
template <typename T> void f2(T, non_pod_tag) { /* non-POD */ }
template <typename T>
void f(T x)
{
// Dispatch to f2 based on tag.
f2(x, podness<std::is_pod<T>::value>());
}
Alternatywą byłoby użyć statycznej funkcji składowej częściowo wyspecjalizowanych typów:
template <typename T, bool> struct f2;
template <typename T>
struct f2<T, true> { static void f(T) { /* POD */ } };
template <typename T>
struct f2<T, false> { static void f(T) { /* non-POD */ } };
template <typename T>
void f(T x)
{
// Select the correct partially specialised type.
f2<T, std::is_pod<T>::value>::f(x);
}
Jakie są plusy i minusy zastosowania jednej metody względem drugiej? Które zaleciłbyś?
Cokolwiek unosi łódź. Uważam, że druga wersja jest bardziej "typetryczna" i atrakcyjna, ponieważ jest mniej pomocniczego kodu i mniej ukrytych pojęć. Dodałbym również argumenty za przekazaniem argumentów! –