Home > database >  Issue while extracting tuple element type in variadic tuple
Issue while extracting tuple element type in variadic tuple

Time:10-16

I'm trying to write generic function that iterates through std::tuple elements. In doing so, i need to extract the element type of the given tuple element that is being processed. However, i'm running into an issue regarding type equality between the extracted type and the actual type of the tuple element. The below code illustrates the problem by adding static_asserts to the extracted type, which (as far as i can tell) should be true in both cases:

#include <tuple>
#include <type_traits>

using TestTuple = std::tuple<int>;

template <std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
foo(std::tuple<Tp...> &) {}

template <std::size_t I = 0, typename... Tp>
    inline typename std::enable_if <
    I<sizeof...(Tp), void>::type foo(std::tuple<Tp...> &output) {
  // Using tuple element
  using ValueType = std::tuple_element<I, std::tuple<Tp...>>;
  static_assert(std::is_same<ValueType, int>::value, "Should be true");

  using ValueType2 = std::remove_reference<decltype(std::get<I>(output))>;
  static_assert(std::is_same<ValueType2, int>::value, "Should be true");
}

void bar() {
  TestTuple t;
  foo(t);
}

Trying to compile through Compiler Explorer, both static_asserts fail on both GCC 11.2 and clang-13; clang output is:

<source>:16:5: error: static_assert failed due to requirement 'std::is_same<std::tuple_element<0, std::tuple<int>>, int>::value' "Should be true"
    static_assert(std::is_same<ValueType, int>::value, "Should be true");
    ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:24:5: note: in instantiation of function template specialization 'foo<0UL, int>' requested here
    foo(t);
    ^
<source>:19:5: error: static_assert failed due to requirement 'std::is_same<std::remove_reference<int &>, int>::value' "Should be true"
    static_assert(std::is_same<ValueType2, int>::value, "Should be true");
    ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 errors generated.
Compiler returned: 1

CodePudding user response:

You're not getting the type of the element of the tuple correctly. They should be

using ValueType = typename std::tuple_element<I, std::tuple<Tp...>>::type;
//                ^^^^^^^^                                         ^^^^^^
static_assert(std::is_same<ValueType, int>::value, "Should be true");

using ValueType2 = typename std::remove_reference<decltype(std::get<I>(output))>::type;
//                 ^^^^^^^^                                                     ^^^^^^
static_assert(std::is_same<ValueType2, int>::value, "Should be true");

Or (since C 14)

using ValueType = std::tuple_element_t<I, std::tuple<Tp...>>;
//                                  ^^
static_assert(std::is_same<ValueType, int>::value, "Should be true");

using ValueType2 = std::remove_reference_t<decltype(std::get<I>(output))>;
//                                      ^^
static_assert(std::is_same<ValueType2, int>::value, "Should be true");
  • Related