如何正确传播通用引用的类型?
How to correctly propagate the type of a universal reference?
我的代码库中有一个情况,我必须实现 std::get()
的通用形式,它适用于任何类型的类似元组的类型。该函数接受对 Tuple
的通用引用和 return 对 Tuple
的第 I
个元素的引用。我不知道如何命名引用的类型。不幸的是,我无法使用 auto
return 类型,只能让编译器自行解决。
这是我的第一次尝试:
#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 拒绝此程序:
$ 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.
我怀疑问题出在我实例化 get_result
的方式上。我做错了什么?
问题是 std::decay
removes cv-qualifiers, and defines the resulting type as the member typedef type. As already TC mentioned in the comments what you need here is 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;
};
我的代码库中有一个情况,我必须实现 std::get()
的通用形式,它适用于任何类型的类似元组的类型。该函数接受对 Tuple
的通用引用和 return 对 Tuple
的第 I
个元素的引用。我不知道如何命名引用的类型。不幸的是,我无法使用 auto
return 类型,只能让编译器自行解决。
这是我的第一次尝试:
#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 拒绝此程序:
$ 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.
我怀疑问题出在我实例化 get_result
的方式上。我做错了什么?
问题是 std::decay
removes cv-qualifiers, and defines the resulting type as the member typedef type. As already TC mentioned in the comments what you need here is 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;
};