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

C++ 如何正确传播通用引用的类型?,c++,perfect-forwarding,universal-reference,C++,Perfect Forwarding,Universal Reference,在我的代码库中,我必须实现一种通用形式的std::get(),它适用于任何类型的元组类型。该函数接受对元组的通用引用,并返回对元组的I第th个元素的引用。我不知道如何命名引用的类型。不幸的是,我无法使用auto返回类型,而只是让编译器来解决它 这是我的第一次尝试: #include <type_traits> #include <tuple> template<class T, class U> struct propagate_reference {

在我的代码库中,我必须实现一种通用形式的
std::get()
,它适用于任何类型的元组类型。该函数接受对
元组的通用引用,并返回对
元组的
I
第th个元素的引用。我不知道如何命名引用的类型。不幸的是,我无法使用
auto
返回类型,而只是让编译器来解决它

这是我的第一次尝试:

#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;
}
#包括
#包括
模板
结构传播\u引用
{
使用类型=U;
};
模板
结构传播\u引用
{
使用type=typename std::add\u lvalue\u reference::type;
};
模板
结构传播\u引用
{
使用type=typename std::add\u rvalue\u reference::type;
};
模板
结构获取结果
{
使用tuple_type=typename std::decay::type;
使用type=typename传播\u引用<
TupleReference,
typename std::元组元素::类型
>::类型;
};
模板
typename-get\u-result::键入my\u-get(元组(&t)
{
返回std::get(std::forward(t));
}
intfoo(conststd::tuple&t)
{
返回我的_get(t);
}
int main()
{
返回0;
}
Clang拒绝此程序:

$ 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.
$clang-std=c++11 test\u get.cpp
test_get.cpp:36:10:错误:将对类型“int”的引用绑定到类型“const”的值(也称为“const int”)会丢弃限定符
返回std::get(std::forward(t));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test_get.cpp:41:10:注意:在函数模板专门化的实例化中,此处请求“my_get”
返回我的_get(t);
^
生成1个错误。
我怀疑问题在于我实例化
获取结果的方式。我做错了什么?

问题是删除了cv限定符,并将结果类型定义为成员类型定义类型。正如评论中已经提到的,您在这里需要的是:

模板
结构获取结果
{
使用tuple\u type=typename std::remove\u reference::type;
使用type=typename传播\u引用<
TupleReference,
typename std::元组元素::类型
>::类型;
};

为什么您无法返回自动?这就是您需要的
删除\u引用
而不是
衰减
。什么东西不能使用
std::get
?您所说的“我不能使用自动”是什么意思?您有“-std=c++11”-这表明您可以用c++11方式使用
auto
,但不能用c++14方式。你还有其他限制吗?一些编码标准?@PiotrNycz:是的,我还有其他限制。我知道,一般来说,退货类型扣减是可能的。我很想了解为什么我最初的尝试没有成功。
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;
};