Feuerteufel
Feuerteufel

Reputation: 581

How to reduce Trait-values of variadic template parameter to one value?

While experimenting with variadic templates I came to a point where it would be useful to make kind of reduction of trait values to one final value via some operation. The use-case for me is:

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)
    {/*...*/}
}

The problem is that the STL traits are all single template typed. My current working solution is:

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);
};

My question is if the STL gives some standardized (probably more convenient) solutionfor that task? And of course I would be happy to here some comments on my current solution, what is bad or what could be better.

Upvotes: 1

Views: 339

Answers (1)

Jarod42
Jarod42

Reputation: 217398

Your solution is linear in term of instantiations (and without the advantage of short-circuit)

You may do it in less instantiations (and still without short-circuit)

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>> {};

You may use std::conjunction which is linear, but with short-circuit.

c++17 and folding expression has nice syntax, has less instantiations (but without short-circuit (for instantiation)):

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

Upvotes: 3

Related Questions