Próbuję wymienić kilka kontroli czasu pracy, aby sprawdza kontrole czasu kompilacji, aby zidentyfikować klasę bazową obiektu z specjalizacjami szablonów.

Kod kompiluje się dobrze, ale nie mogę dowiedzieć się, dlaczego oświadczenie enable_if zawsze kończy się nieprawidłowe lub równe void, ponieważ zawsze jestem wylądowany na strukturze szablonu bazowego.

#include <iostream>
#include <type_traits>
using namespace std;

struct BaseOne {};
struct DerivedOne : BaseOne {};
struct BaseTwo {};
struct DerivedTwo : BaseTwo {};
struct Default {};

template<typename T, typename = void>
struct get_category_impl {
    static constexpr int value = 0;
};

template<typename T>
struct get_category_impl<T, typename enable_if<is_base_of<BaseOne, T>::value, T>::type> {
    static constexpr int value = 1;
};

template<typename T>
struct get_category_impl<T, typename enable_if<is_base_of<BaseTwo, T>::value, T>::type> {
    static constexpr int value = 2;
};

template<typename T>
constexpr int get_category = get_category_impl<T>::value;

int main() {
    cout << get_category<BaseOne>    << "\n"; // prints 0
    cout << get_category<DerivedOne> << "\n"; // prints 0
    cout << get_category<BaseTwo>    << "\n"; // prints 0
    cout << get_category<DerivedTwo> << "\n"; // prints 0
    cout << get_category<Default>    << "\n"; // prints 0
}
2
VincentDM 28 październik 2020, 01:38

1 odpowiedź

Najlepsza odpowiedź

Drugi parametr do enable_if nie musi być określony. Jeśli go określi, musi być jakoś rozwiązać do void. Ponieważ określono drugi parametr jako T, to nie działa.

Zamiast tego zrobić:

template<typename T>
struct get_category_impl<T, typename enable_if<is_base_of<BaseOne, T>::value>::type> {
                                                                         // ^  No T 
    static constexpr int value = 1;
};

I podobnie jak inna specjalizacja.

Oto Demo.

5
cigien 27 październik 2020, 23:02