„Co się stało z moją SFINAE” redux: członkowie klas szablonów warunkowych?

Jestem nowy w pisaniu kodu metaprogramowania szablonu (a nie tylko po jego przeczytaniu). Więc mam problemy z noobem. Jeden z nich jest dość dobrze podsumowany przez ten post, który został napisany jako nie-SO„Co się stało z moją SFINAĄ?”, które będę C ++ 11-ize jak to:

(Uwaga: Dałem metodom różne nazwy tylko po to, by pomóc w diagnozie błędów w tym przykładzie „eksperymentu myślowego”. ZobaczNotatki @ R.MartinhoFernandes dlaczego w rzeczywistości nie wybierzesz takiego podejścia w przypadku braku przeciążenia.)

#include <type_traits>

using namespace std;

template <typename T>
struct Foo {
    typename enable_if<is_pointer<T>::value, void>::type
    valid_if_pointer(T) const { }

    typename disable_if<is_pointer<T>::value, void>::type
    valid_if_not_pointer(T) const { }
};

int main(int argc, char * argv[])
{
    int someInt = 1020;
    Foo<int*>().valid_if_pointer(&someInt);    
    Foo<int>().valid_if_not_pointer(304);

    return 0;
}

@Alf mówi, że to, co stało się z SFINAE, to „Nie było go na pierwszym miejscu” i daje sugestię, która kompiluje, ale szablonuje funkcje zamiast klasy. To może być właściwe dla niektórych sytuacji, ale nie dla wszystkich.(Na przykład: Szczególnie próbuję napisać kontener, który może zawierać typy, które mogą lub nie mogą być konstruowane jako kopie, i muszę na tej podstawie włączać i wyłączać metody).

Jako obejście, dałem ten strzał ... który wydaje się działać poprawnie.

#include <type_traits>

using namespace std;

template <typename T>
struct FooPointerBase {
    void valid_if_pointer(T) const { }
};

template <typename T>
struct FooNonPointerBase {
    void valid_if_not_pointer(T) const { }
};

template <typename T>
struct Foo : public conditional<
    is_pointer<T>::value, 
    FooPointerBase<T>,
    FooNonPointerBase<T> >::type {
};

int main(int argc, char * argv[])
{
    int someInt = 1020;
#if DEMONSTRATE_ERROR_CASES
    Foo<int*>().valid_if_not_pointer(&someInt);
    Foo<int>().valid_if_pointer(304);
#else
    Foo<int*>().valid_if_pointer(&someInt);
    Foo<int>().valid_if_not_pointer(304);
#endif
    return 0;
}

Ale jeśli to nie jest złamane(czy to?), z pewnością nie postępuje zgodnie z dobrą ogólną metodologią włączania i wyłączania metod w klasie z szablonami opartą na wąchaniu typu dla cech. Czy jest lepsze rozwiązanie?

questionAnswers(2)

yourAnswerToTheQuestion