24

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

现在假设我想一次重命名(或alias,或更准确地说是forward)这些函数(即能够为同一个函数使用不同的名称而无需重写它)。这样,在代码的其他部分,我可以用不同的名称使用它,而无需修改上述代码。

这是将(别名/转发)重命名fun为的正确方法gun吗?

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)
}}

EDIT2:我认为异常策略也可以合并到别名中:

#define ALIAS_FUNCTION(OriginalnamE, AliasnamE) \
template <typename... Args> \
inline auto AliasnamE(Args&&... args) \
  noexcept(OriginalnamE(std::forward<Args>(args)...)) \
->decltype(OriginalnamE(std::forward<Args>(args)...)){\
    return OriginalnamE(std::forward<Args>(args)...);}

但还没有测试它。 您必须键入三遍

4

1 回答 1

13

真的一般吗?

是的。

这是最简单的方法吗?

是的(很遗憾)。

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

是的。

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

是的,如果里面的表达式decltype产生错误(即,fun不存在,可能是由于 SFINAE on fun),这也会触发 SFINAE gun,将其从重载集中删除。

如果原始函数返回引用怎么办?decltype 不会删除引用类型吗?(例如double& fun(double& x){return x;})。

不,为什么会这样?

成员函数也是如此,尽管我猜这必须通过修改类来完成。

这不是一个问题。关于成员函数可以说什么?以上所有内容同样适用。

于 2012-12-04T15:27:55.587 回答