0

Having a tuple of types, I want to generate the tuple containing all the possible pairs. I'm having trouble understanding why the pairs with the last types in the first position (like: {B,_}) appear multiple times.

#include <iostream>
#include <type_traits>
#include <tuple>
#include <utility>
struct A; struct B; struct C; struct D; struct E; struct F;
using Types = std::tuple<A,B>;

template <typename TupleAll, typename Tuple1, typename Tuple2>
struct PairsGenerator {
    using Type = std::tuple<>;
};
template <typename TupleAll, typename T, typename U, typename... Ts, typename... Us>
struct PairsGenerator<TupleAll, std::tuple<T, Ts...>,  std::tuple<U, Us...>> {
    using Type = decltype(std::tuple_cat(
        std::declval<std::tuple<std::pair<T, U>>>(),
        std::declval<typename PairsGenerator<TupleAll, std::tuple<T, Ts...>, std::tuple<Us...>>::Type>(),
        std::declval<typename PairsGenerator<TupleAll, std::tuple<Ts...>, TupleAll>::Type>()));
};
template <typename TypesTuple>
using Pairs = typename PairsGenerator<TypesTuple, TypesTuple, TypesTuple>::Type;

int main() {
    //std::cout << typeid(decltype(std::declval<Pairs<Types>>())).name() << std::endl;
    std::cout << std::boolalpha << std::is_same_v<std::tuple<
        std::pair<A,A>,
        std::pair<A,B>,
        std::pair<B,A>,
        std::pair<B,B>,
        std::pair<B,A>,
        std::pair<B,B>
    >, Pairs<Types>>;
}

Returns true, instead it should be, but the following is false

std::cout << std::boolalpha << std::is_same_v<std::tuple<
    std::pair<A,A>,
    std::pair<A,B>,
    std::pair<B,A>,
    std::pair<B,B>
>, Pairs<Types>>;
barsdeveloper
  • 930
  • 8
  • 28
  • Related to [how-to-create-the-cartesian-product-of-a-type-list](https://stackoverflow.com/questions/9122028/how-to-create-the-cartesian-product-of-a-type-list). – Jarod42 Feb 06 '20 at 15:51
  • I didn't ask how. I already did it. I asked what did I miss from the code above. – barsdeveloper Feb 06 '20 at 16:02
  • 1
    Your logic is wrong: with your code you do `ab*ab = {aa, ab*b, b*ab}` with "expected" `ab*b = {ab, bb}` and `b*ab= {ba, bb}` So the duplicate `bb`. – Jarod42 Feb 06 '20 at 16:07
  • And currently `ab*b` result in `ab, ba, bb`. changing `std::tuple, TupleAll>` to `std::tuple, std::tuple>` remove `ba`. – Jarod42 Feb 06 '20 at 16:11

1 Answers1

1

In this line

std::declval<typename PairsGenerator<TupleAll, std::tuple<Ts...>, TupleAll>::Type>()));

The second TupleAll should be std::tuple<U, Us...>. Like it is now your code will do much weirder stuff if your input has a length greater than 2. To me it seems as if you can get rid of the TupleAll parameter altogether.

n314159
  • 4,990
  • 1
  • 5
  • 20