AOK AOK - 2 years ago 120
C++ Question

Implementing mathematical complement logic on variadic template parameters


I have a class that defines a

constexpr size_t dimensions
. In this class, I implemented an
EvaluateOver<Dimensions...>(Lambda F)
which does something over the dimensions I specify. For example, say
dimensions=4
and
f
is some lambda expression:

MyClass.EvaluateOver<0,2>(f);


will perform
f
with respect to 0 and 2 by doing the following expansion:

template<size_t... Dims, typename Lambda>
inline auto EvaluateOver(const Lambda& F) const
{
F(std::get<Dims>(_memberTupleDataContainer)...);
}


Now I want another member function that will evaluate over the unspecified dimensions. So
EvaluateOverOthers<0,2>(f)
will perform its operation on dimensions 1 and 3.

Ideally, I am thinking of the following:

template<size_t... Dims, typename Lambda>
inline auto EvaluateOverOthers(const Lambda& F) const
{
EvaluateOver<
// variadic parameter that does the mathematical complement of
// Dims... with a variadic expansion of dimensions
>(F);
}

Answer Source

Following might help:

namespace details
{

template <typename Seq1, typename Seq2, typename Res = std::index_sequence<>>
struct minus;

// Nothing more to remove
template <std::size_t ... Is1, std::size_t... IRes>
struct minus<std::index_sequence<Is1...>,
             std::index_sequence<>,
             std::index_sequence<IRes...>>
{
    using type = std::index_sequence<IRes..., Is1...>;
};

// Remove front elements as they are equal.
template <std::size_t I, std::size_t ... Is1, std::size_t ... Is2, std::size_t... IRes>
struct minus<std::index_sequence<I, Is1...>,
             std::index_sequence<I, Is2...>,
             std::index_sequence<IRes...>>
{
    using type = typename minus<std::index_sequence<Is1...>,
                                std::index_sequence<Is2...>,
                                std::index_sequence<IRes...>>::type;
};

// Add front element to result.
template <std::size_t I1, std::size_t I2,
          std::size_t ... Is1, std::size_t ... Is2,
          std::size_t... IRes>
struct minus<std::index_sequence<I1, Is1...>,
             std::index_sequence<I2, Is2...>,
             std::index_sequence<IRes...>>
{
    using type = typename minus<std::index_sequence<Is1...>,
                                std::index_sequence<I2, Is2...>,
                                std::index_sequence<IRes..., I1>>::type;
};

}

template <std::size_t N, typename Seq>
using complement = details::minus<std::make_index_sequence<N>, Seq>;

template <std::size_t N, typename Seq>
using complement_t = typename complement<N, Seq>::type;

// Some test
static_assert(std::is_same<std::index_sequence<0, 3>,
                    complement_t<4, std::index_sequence<1, 2>>>::value, "!");

And then

template<size_t... Is, typename Lambda>
auto EvaluateOver(const Lambda& F, std::index_sequence<Is...>) const
{
    return F(std::get<Is>(_memberTupleDataContainer)...);
}

template<size_t... Dims, typename Lambda>
auto EvaluateOver(const Lambda& F) const
{
    return EvaluateOver(F, std::index_sequence<Is...>{});
}

template<size_t... Is, typename Lambda>
auto EvaluateOverOthers(const Lambda& F) const
{
    return EvaluateOver(F, complement_t<_dimension, std::index_sequence<Is...>>{});
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download