考虑一个类A
,我该如何编写一个与
A& pretty(A& x)
{
/* make x pretty */
return x;
}
A pretty(A&& x)
{
/* make x pretty */
return x;
}
知道我想:
以完全相同的方式修改参数(x
),与参数是左值引用还是左值引用无关(实际上,两个部分/* make x pretty */
是相同的)因此具有单一功能;
避免不必要的复制;
能够使用该函数修改变量;
能够“管道”函数调用,无论参数是rvalue还是左值。
作为3.和4的示例,请考虑以下用例:
void read_A(const A& x) { /* ... */ }
void take_A(A&& x) { /* ... */ }
A x();
read_A(pretty(x));
take_A(pretty(A()));
我的想法是利用转发引用,同时将允许的参数限制为A
的引用。但是返回类型呢?
template<typename T>
std::enable_if_t<std::is_same<T, A>::value>
/*???*/ pretty(T&& x)
{
/* make x pretty */
return x; //?
}
答案 0 :(得分:3)
为什么不简单地写
#include <iostream>
template <class T>
T somefunc(T&& a) {
/* do something with a */
std::cout << __PRETTY_FUNCTION__ << '\n';
return std::forward<T>(a);
}
int main(int argc, char* argv[]) {
int a = 5;
somefunc(a);
somefunc(5);
return 0;
}
将返回
T somefunc(T &&) [T = int &]
T somefunc(T &&) [T = int]
如您所见,这些功能具有您想要的签名。在第一次通话中,T
获得int &
,因此获得int &
的返回值。在第二个中,你有T = int = int &&
,这也是你想要的。
编辑。顺便说一句,您最初考虑应用std::is_same
来禁用A
以外的类型的重载解析似乎也是错误的。根据{{3}},
如果
T
和U
使用相同的const-volatile资格来命名相同的类型,则提供等于true
的成员常量值。否则值为false
。
因此,您可能希望使用decay
或至少remove_cv
和remove_reference
的组合来应用您想要的逻辑。下面是上面代码的修改版本,现在包含重载决策启用程序。
#include <iostream>
#include <type_traits>
template <class T> T somefunc(T &&a) {
/* do something with a */
std::cout << __PRETTY_FUNCTION__ << '\n';
return std::forward<T>(a);
}
template <class T, typename std::enable_if<
std::is_same<typename std::decay<T>::type, float>::value,
int>::type = 0>
T onlyfloat_correct(T &&a) {
/* do something with a */
std::cout << __PRETTY_FUNCTION__ << '\n';
return std::forward<T>(a);
}
template <class T,
typename std::enable_if<std::is_same<T, float>::value, int>::type = 0>
T onlyfloat_wrong(T &&a) {
/* do something with a */
std::cout << __PRETTY_FUNCTION__ << '\n';
return std::forward<T>(a);
}
int main(int argc, char *argv[]) {
int a = 5;
const float b = 5;
somefunc(a);
somefunc(5);
onlyfloat_correct(b);
// onlyfloat_wrong(b);
return 0;
}
答案 1 :(得分:0)
您根本不需要模板。您可以利用rvalue引用是左值引用过载中的左值全部调用pretty
这一事实,因此您只需要在左值过载中编写make x pretty
逻辑。看起来像是
A& pretty(A& x)
{
/* make x pretty */
return x;
}
A pretty(A&& x)
{
return std::move(pretty(x));
}