如何正确传播通用引用的类型?

时间:2015-12-07 19:57:16

标签: c++ perfect-forwarding universal-reference

我的代码库中存在一种情况,我必须实现std::get()的通用形式,它适用于任何类型的类似Tuple的类型。该函数接受对Tuple的通用引用,并返回对I的{​​{1}}元素的引用。我不知道如何命名引用的类型。不幸的是,我无法使用Tuple返回类型,只是让编译器弄明白。

这是我的第一次尝试:

auto

Clang拒绝这个程序:

#include <type_traits>
#include <tuple>

template<class T, class U>
struct propagate_reference
{
  using type = U;
};

template<class T, class U>
struct propagate_reference<T&,U>
{
  using type = typename std::add_lvalue_reference<U>::type;
};

template<class T, class U>
struct propagate_reference<T&&,U>
{
  using type = typename std::add_rvalue_reference<U>::type;
};

template<size_t I, class TupleReference>
struct get_result
{
  using tuple_type = typename std::decay<TupleReference>::type;

  using type = typename propagate_reference<
    TupleReference,
    typename std::tuple_element<I,tuple_type>::type
  >::type;
};

template<size_t I, class Tuple>
typename get_result<I,Tuple&&>::type my_get(Tuple&& t)
{
  return std::get<I>(std::forward<Tuple>(t));
}

int foo(const std::tuple<int>& t)
{
  return my_get<0>(t);
}

int main()
{
  return 0;
}

我怀疑问题与我实例化$ clang -std=c++11 test_get.cpp test_get.cpp:36:10: error: binding of reference to type 'int' to a value of type 'const __tuple_element_t<0UL, tuple<int> >' (aka 'const int') drops qualifiers return std::get<I>(std::forward<Tuple>(t)); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ test_get.cpp:41:10: note: in instantiation of function template specialization 'my_get<0, const std::tuple<int> &>' requested here return my_get<0>(t); ^ 1 error generated. 的方式有关。我做错了什么?

1 个答案:

答案 0 :(得分:3)

问题是std::decay删除了cv-qualifiers,并将结果类型定义为成员typedef类型。正如评论中提到的TC,您需要的是std::remove_reference

template<size_t I, class TupleReference>
struct get_result
{
  using tuple_type = typename std::remove_reference<TupleReference>::type;

  using type = typename propagate_reference<
    TupleReference,
    typename std::tuple_element<I,tuple_type>::type
  >::type;
};

Live Demo