2016-11-10 7 views
1

При экспериментировании с вариативными шаблонами я подошел к точке, где было бы полезно сделать некоторое уменьшение значений признаков до одного конечного значения с помощью некоторой операции. Вариант использования для меня:Как уменьшить значения значений параметра вариационного шаблона до одного значения?

constexpr bool and(bool lhs, bool rhs){return lhs && rhs;} 

struct Foo 
{ 
    template< 
     typename ...Ts> 
    Foo(
     Ts&&... args) 
      noexcept(TraitReduction<std::is_nothrow_move_constructible, and, Ts...>::value) 
    {/*...*/} 
} 

Проблема заключается в том, что в свойствах STL заданы только один шаблон. Мой текущий рабочий раствор:

template< 
    template<typename> class TraitT, 
    bool (*Operator)(bool,bool), 
    typename T1, 
    typename ...Ts> 
struct TraitReduction 
{ 
    static bool const value = TraitT<T1>::value; 
}; 

template< 
    template<typename> class TraitT, 
    bool (*Operator)(bool,bool), 
    typename T1, 
    typename T2, 
    typename ...Ts> 
struct TraitReduction< 
    TraitT, 
    Operator, 
    T1, 
    T2, 
    Ts...> 
{ 
    static bool const value = (*Operator)(
     TraitT<T1>::value, 
     TraitReduction<TraitT, Operator, T2, Ts...>::value); 
}; 

Мой вопрос, если STL дает некоторые стандартизированные (вероятно, более удобно) solutionfor эту задачу? И, конечно, я был бы рад получить некоторые комментарии к моему текущему решению, что плохо или что может быть лучше.

+0

'noexcept ((is_nothrow_move_constructible {} и ...)) ' – 0x499602D2

+0

Этот конкретный случай выглядит как работа для [' std :: conj'] (http://en.cppreference.com/w/cpp/types/conjunction), но если вы ищете более обобщенный подход, то это недостаточно – krzaq

+0

Вы знаете, что 'и' это другое написание '&&', правильно? –

ответ

3

Ваше решение является линейным в срок конкретизации (и без преимущества короткого замыкания)

Вы можете сделать это менее конкретизации (и до сих пор без короткого замыкания)

template <bool...> struct bools{}; 

template <template <typename> Trait, typename ... Ts> 
struct all_of : std::is_same<bools<true, Trait<Ts>::value...>, 
          bools<Trait<Ts>::value..., true>> {}; 

Вы можете используйте std::conjunction, который является линейным, но с коротким замыканием.

C++ 1z и складывание выражение имеет приятный синтаксис, имеет меньше инстанцирований (но без короткого замыкания (для конкретизации)):

(Trait<Ts>::value && ...) 
+0

Интересный трюк с 'true' в первой и последней позиции. – Orient

+0

Сравнение двух типов (специализации шаблонов классов с длинными списками аргументов шаблона) является линейным по числу * имен шаблонов * и * type-ids * (те из них, которые не являются * template-ids *) и 'std :: conj' также линейно. Что предпочтительнее? – Orient

+0

Возможно, даже лучше использовать псевдоним типа для определения 'all_of':' template < ... > using all_of = typename std :: is_same < ... > :: type; ' – Orient