2016-07-13 4 views
1

Скажем, у меня есть класс X1, который происходит от Y и другого класса X2. Y и X2 имеют специальную черту Z_trait.Можно ли пересечь класс, чтобы узнать, имеет ли класс или любая его база конкретный признак?

Теперь у меня есть функция шаблона, и я хочу проверить, что параметр имеет определенный признак.

Это то, что у меня есть:

#include<type_traits> 

template <typename T> 
struct Y  {}; 
struct X1 : Y<int> {}; 
struct X2  {}; 
struct Z_trait {}; 

template <typename Container> 
struct has_trait; 

template <> 
struct has_trait<X2> 
{ 
    typedef Z_trait type; 
}; 

template <typename T> 
struct has_trait<Y<T>> 
{ 
    typedef Z_trait type; 
}; 

template <typename Container> 
void fn(Container& container) 
{ 
    static_assert(std::is_same<typename has_trait<Container>::type, Z_trait>::value 
    , "must have Z_trait"); 
    Container* x = &container; 
    ++x; 
} 

int main() 
{ 
    X1 x1; 
    X2 x2; 
    Y<char> y; 

    fn(x1); 
    fn(x2); 
    fn(y); 

    return 0; 
} 

демо

Я хочу, чтобы это так, что has_trait даст Z_trait для всех трех типов. Как мне это сделать? Есть ли способ итерации по всем базовым классам, или есть какой-то более простой метод для проверки качества?

УКАЗЫВАЙТЕ, что я не использую шаблон использования. Причина этого в том, что VS2013 не поддерживает это полностью.

О, и FYI, я не хочу менять реализацию X1, X2 или Y.

ответ

1

Вы хотите специализироваться has_trait<> для потомков, а не только для базы:

#include<type_traits> 

struct Y  {}; 
struct X1 : Y {}; 
struct X2  {}; 
struct Z_trait {}; 

template <typename Container, typename = void> 
struct has_trait; 

template <typename T> 
struct has_trait<T, typename std::enable_if< std::is_base_of<X2, T>::value >::type > 
{ 
    typedef Z_trait type; 
}; 

template <typename T> 
struct has_trait<T, typename std::enable_if< std::is_base_of<Y, T>::value >::type > 
{ 
    typedef Z_trait type; 
}; 

template <typename Container> 
void fn(Container& container) 
{ 
    static_assert(std::is_same<typename has_trait<Container>::type, Z_trait>::value 
    , "must have Z_trait"); 
    Container* x = &container; 
    ++x; 
} 

int main() 
{ 
    X1 x1; 
    X2 x2; 
    Y y; 

    fn(x1); 
    fn(x2); 
    fn(y); 

    return 0; 
} 

Кроме того, вы могли бы рассмотреть static constexpr const bool has_z_trait = true; или static bool hasTrait(const ZTrait&) { return true; }, это статическое утверждают проще имхо.

+0

Причина, по которой я использую типы, а не значение, заключается в том, что я использую черты типов из библиотеки std. Этот вид работ, но если X1 является шаблоном, он не работает. Я получаю ошибку «не вычитается в частичной специализации», если я пытаюсь добавить аргументы шаблона в список. – Adrian

+0

См. [Здесь] (http://cpp.sh/2h5z) для демонстрации того, что я имею в виду. – Adrian

+2

@Adrian: вы должны * исправить * свои черты, если 'Y' является шаблоном: [Demo] (http://coliru.stacked-crooked.com/a/46f9d20bc37a27bd). – Jarod42

Смежные вопросы