【问题标题】:Issue while extracting tuple element type in variadic tuple在可变元组中提取元组元素类型时出现问题
【发布时间】:2021-12-02 21:46:12
【问题描述】:

我正在尝试编写遍历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_asserts 在 GCC 11.2 和 clang-13 上均失败;叮当输出是:

<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

【问题讨论】:

    标签: c++ templates tuples variadic-templates


    【解决方案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");
    

    【讨论】:

      猜你喜欢
      • 2022-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多