在可变元组中提取元组元素类型时出现问题

Issue while extracting tuple element type in variadic tuple

我正在尝试编写遍历 std::tuple 元素的通用函数。为此,我需要提取正在处理的给定元组元素的元素类型。但是,我 运行 遇到了有关元组元素的提取类型和实际类型之间的类型相等性的问题。下面的代码通过向提取的类型添加 static_asserts 来说明问题,这(据我所知)在两种情况下都应该是正确的:

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

尝试通过 Compiler Explorer 进行编译,static_assert 在 GCC 11.2 和 clang-13 上均失败; clang 输出是:

<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

您没有正确获取元组元素的类型。他们应该是

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

或(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");