在C ++中重命名(别名/转发)函数的最佳方法是什么?

时间:2012-12-04 08:46:44

标签: c++ templates c++11 variadic-templates perfect-forwarding

(我将此问题限制在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

现在假设我想要重命名(或别名,或者转发更精确)这些功能,一下子(即能够为同一个函数使用不同的名称而不重写它)。这样,在代码的其他部分,我可以使用不同的名称,而无需修改上述代码。

这是重命名(别名/转发)fungun的正确方法吗?

template<typename... Args> 
inline auto gun(Args&&... args)->decltype(fun(std::forward<Args>(args)...)){
    return fun(std::forward<Args>(args)...);
}
  • 真的一般吗?
  • 这是最简单的方法吗?
  • 这是最佳方式吗? (例如可以内联,没有不必要的副本)
  • 如果原始功能有一些SFINAE功能怎么办? (例如template<class A, class B, class C, class = std::enable_if< ... >::type>),decltype会在所有情况下转移SFINAE吗?
  • 如果原始函数返回引用怎么办?不是decltype会删除引用类型吗? (例如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)...); \
}

然后你就像这样使用它:

namespace NS1{namepsace NS2{
  ALIAS_FUNCTION(NSA::fun, gun); // second argument (target name can't have namespace)
}}

1 个答案:

答案 0 :(得分:10)

  

真的一般吗?

  

这是最简单的方法吗?

是的(遗憾的是)。

  

这是最佳方式吗? (例如可以内联,没有不必要的副本)

  

如果原始功能有一些SFINAE功能怎么办? (例如template<class A, class B, class C, class = std::enable_if< ... >::type>),在所有情况下都会转换SFINAE吗?

是的,如果decltype内的表达式产生错误(即,fun不存在,可能是由于fun上的SFINAE),这将触发{{1}的SFINAE同时,将它从重载集中删除。

  

如果原始函数返回引用怎么办?不是decltype会删除引用类型吗? (例如gun)。

不,为什么会这样?

  

关于成员函数也可以这么说,尽管我必须修改这个类。

这不是问题。关于会员职能可以说什么?以上所有内容同样适用。