(我將這個問題限制在C++ 11中,因爲我相信在C++ 98中沒有這樣做的一般方法)。在C++中重命名(別名/轉發)函數的最佳方式是什麼?
假設我有一個複雜的(在簽名計算)設置模板功能和/或重載函數,我想以完全相同的方式來使用這些功能,但使用不同的名稱(即別名)。
例如:
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
現在假設我想重命名(或別名,或着更精確)這些功能,都在一次(即能夠使用同一個功能的不同名稱,而不用重寫它)。這樣,在代碼的其他部分,我可以使用不同的名稱並且不需要修改上面的代碼。
這是正確的方式重命名(別名/轉發)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)
}}
我認爲這很好。 'decltype'獲得正確的類型(即'&'用於返回左值引用的函數,'&&'用於返回右值引用的函數,否則爲非引用)。 –
拜託,如果你描述你實際在做什麼,你會讓每個人都變得更加輕鬆。你不重命名*任何*。原來的名字仍然存在。您正在轉發,或提供別名或包裝函數。這與重命名沒有任何關係。重命名意味着*更改*名稱,使舊名稱消失,轉而使用新名稱 – jalf
@jalf,好點。我想,讓原來的名字消失很難。我想象的唯一方法是將原始定義放入一個未命名的名稱空間中。但是,是的,這不是主意。 – alfC