Tim*_*ann 4 c++ templates c++11
我正在学习模板并尝试实现此方法:
template <typename Func, typename Left, typename Right>
void flipArgs(Func* function, Left&& leftArg, Right&& rightArg) {
function(std::forward<Right>(rightArg), std::forward<Left>(leftArg));
}
Run Code Online (Sandbox Code Playgroud)
它需要一个函数和两个参数,并在翻转两个参数的情况下调用给定的函数.
它的功能很好,例如:
void test1(std::string, int) {
}
Run Code Online (Sandbox Code Playgroud)
当我尝试这个功能时:
template <typename T>
void test2(T&& a, int) {
}
Run Code Online (Sandbox Code Playgroud)
附:
string s("test");
flip(test2<string>, 42, s);
Run Code Online (Sandbox Code Playgroud)
编译器(g ++ 4.7.1)告诉我:
错误:无法将'std :: basic_string'左值绑定到'std :: basic_string &&'
我认为一个函数参数,如T&&可以绑定rvalue和lvalue引用的特殊情况?我究竟做错了什么?
我认为一个函数参数,例如
T&&可以绑定到[rvalues和lvalues]的特殊情况?
它是.它基本上意味着模板可以为左值和右值具有不同的实例.
但是......当您明确T地string进入时test2<string>,您正在选择一个特定的实例:void test2(string&&, int).string&&不再是那种特殊情况.string&&只能绑定到字符串rvalues.没有一个实例可以绑定rvalues和lvalues.
一般来说,我建议不要显式传递函数模板参数(除非那些是有意的,比如std::forward或std::make_unique).
在这种情况下,您可以改为强制绑定到左值的实例化之一.有点像flip(test2<string&>, 42, s);,会实例化的东西void test2(string&, int).
如果你真的想传递一个flip可以接受左值和右值的参数,你需要一个多态函数对象:
struct test2 {
template <typename T>
void operator()(T&& a, int) const {
}
};
flip(test2{}, 42, s);
Run Code Online (Sandbox Code Playgroud)
这里的关键是,在传递参数时,不会决定使用哪种特化,而是在稍后使用该参数时.
为了完整起见,在C++ 14中,您实际上可以使用新的lambda语法创建匿名多态函数对象:
auto test2 = [](auto&& a, int) {};
flip(test2, 42, s);
Run Code Online (Sandbox Code Playgroud)