alf*_*lfC 20 c++ templates variadic-templates perfect-forwarding c++11
(我将这个问题限制在C++ 11中,因为我相信在C++ 98中没有通用的方法).
假设我有一组复杂的(在签名方面)模板函数和/或重载函数,我想以完全相同的方式使用这些函数,但使用不同的名称(即别名).
例如:
template<class A, class B, class C>
D fun(A a, B& b, C&& c){ ... }
template<class E, class F>
G fun(H<E> he, F& f){ ... }
... many other versions of fun
Run Code Online (Sandbox Code Playgroud)
现在假设我想要同时重命名(或别名,或转发为更精确)这些函数(即能够为同一函数使用不同的名称而不重写它).这样,在代码的其他部分,我可以使用不同的名称,而无需修改上述代码.
这是正确的方式重命名(别名/转发)fun
到gun
?
template<typename... Args>
inline auto gun(Args&&... args)->decltype(fun(std::forward<Args>(args)...)){
return fun(std::forward<Args>(args)...);
}
Run Code Online (Sandbox Code Playgroud)
template<class A, class B, class C, class = std::enable_if< ... >::type>
),是否会decltype
在所有情况下转移SFINAE?double& fun(double& x){return x;}
).澄清:gun
永远不会完全正确 fun
,因为实例将具有不同的地址,但我正在寻找的是对通用编码的观点进行重命名.
评论:我觉得很奇怪,几乎所有东西都可以重命名/转发,名称空间,类型(typedef
)和模板类型using typedef
,但不是函数(或者那个成员函数).
编辑:为了完整性,因为这似乎是这样做的方式,这里我添加了一个宏来定义函数别名:
#define ALIAS_FUNCTION(OriginalnamE, AliasnamE) \
template <typename... Args> \
inline auto AliasnamE(Args&&... args) -> decltype(OriginalnamE(std::forward<Args>(args)...)) { \
return OriginalnamE(std::forward<Args>(args)...); \
}
Run Code Online (Sandbox Code Playgroud)
然后你像这样使用它:
namespace NS1{namepsace NS2{
ALIAS_FUNCTION(NSA::fun, gun); // second argument (target name can't have namespace)
}}
Run Code Online (Sandbox Code Playgroud)
Xeo*_*Xeo 11
它真的一般吗?
是.
这是最简单的方法吗?
是的(遗憾的是).
这是最佳方式吗?(例如可以内联,没有不必要的副本)
是.
如果原始功能有一些SFINAE功能怎么办?(例如
template<class A, class B, class C, class = std::enable_if< ... >::type>
),在所有情况下,是否会转移SFINAE?
是的,如果内部表达式decltype
产生错误(即,fun
不存在,可能是由于SFINAE打开fun
),这将触发SFINAE gun
,并将其从过载集中移除.
如果原始函数返回引用怎么办?不是decltype会删除引用类型吗?(例如
double& fun(double& x){return x;}
).
不,为什么会这样?
关于成员函数也是如此,尽管我必须修改这个类.
这不是一个问题.关于会员职能可以说什么?以上所有内容同样适用.