Hug*_*ues 4 c++ templates return-type c++11
关于模板化函数中的完美转发的广泛讨论,允许有效地将左值或右值参数作为参数传递给其他函数.
但是,我无法找到关于完美回归或等效完美传递的讨论.(相关问题完美传递并未完全解决此问题.)
考虑修改范围的函数的情况,并应返回修改的范围.我们需要两个单独的函数来有效地解决左值和右值参数的情况:
// Given a reference to an lvalue range, return a reference to the same modified range.
// (There is no allocation or move.)
template<typename T> T& sortr(T& r) {
std::sort(std::begin(r),std::end(r));
return r;
}
// Given an rvalue range, return the same range via (hopefully) a move construction.
template<typename T> T sortr(T&& r) {
std::sort(std::begin(r),std::end(r));
return std::move(r);
}
Run Code Online (Sandbox Code Playgroud)
当然,包括这两个定义会导致歧义错误,因为第二个定义也与左值引用匹配.
一个激励性的例子(和测试用途)如下:
#include <iostream>
#include <vector>
#include <algorithm>
std::ostream& operator<<(std::ostream& os, const std::vector<int>& v) {
os << "["; for (int i : v) { os << " " << i; } os << " ]\n"; return os;
}
int main() {
std::vector<int> c1{3,4,2,1};
std::cerr << sortr(c1) << sortr(std::vector<int>({7,6,5,8}));
}
Run Code Online (Sandbox Code Playgroud)
我们可以定义sortr使用单个template<typename T>定义的两个版本吗?
挑战在于声明返回类型T&&只会导致(在模板匹配之后)T&&或T&返回类型,而不是T.
是否可以使用返回类型的元编程来定义适当的模板函数?类似于以下内容:
template<typename T> auto sortr(T&& r) ->
typename std::conditional<std::is_lvalue_reference<T>::value, T&, T>::type
{
std::sort(std::begin(r),std::end(r));
return std::forward<T>(r);
}
Run Code Online (Sandbox Code Playgroud)
这似乎有效,但我不确定它是否安全和明智.欢迎任何指导.
您需要使用通用引用.在这种情况下,您可以只返回T,但您需要将模板功能更改为:
template<typename T> T sortr(T && r) {
std::sort(std::begin(r),std::end(r));
return std::forward<T>(r);
}
Run Code Online (Sandbox Code Playgroud)
完整示例:
#include <iostream>
#include <utility>
#include <type_traits>
#include <vector>
#include <algorithm>
template<typename T> T sortr(T && r) {
std::sort(std::begin(r),std::end(r));
return std::forward<T>(r);
}
std::vector<int> foo()
{
return std::vector<int>(5,2);
}
void test( std::vector<int> & )
{
std::cout<<"lvalue" << std::endl;
}
void test( std::vector<int> && )
{
std::cout<<"rvalue" << std::endl;
}
int main()
{
std::vector<int> v(1,6);
test( sortr( foo() ) );
test( sortr( v ) );
}
Run Code Online (Sandbox Code Playgroud)
如果您不知道什么是通用参考,请参阅Scott Meyers的演讲.