(I'll restrict this question to C++11, since I believe there is no general way to do this in C++98).
Supposed I have a complicated (in terms of signature) set of template functions and/or overloaded functions, and I want to use these functions in the exact same way but using a different name (that is, an alias).
For example:
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
Now suppose that I want to rename (or alias, or forward to be more precise) these functions, all at once (i.e. be able to use a different name for the same function without rewriting it). Such that, in other parts of the code I can use it with a different name and without modifying the above code.
Is this the correct way to rename (alias/forward) fun
into gun
?
template<typename... Args>
inline auto gun(Args&&... args)->decltype(fun(std::forward<Args>(args)...)){
return fun(std::forward<Args>(args)...);
}
- Is it truly general?
- Is this the simplest way?
- Is this the optimal way? (e.g. can be inlined, no unnecessary copies)
- What if the original function had some SFINAE features? (e.g.
template<class A, class B, class C, class = std::enable_if< ... >::type>
), will decltype
transfer the SFINAE in all cases?
- What if the original function returned references? Isn't the decltype going to remove the references type?. (e.g.
double& fun(double& x){return x;}
).
- Can same be said about member functions?
Clarification: gun
is never going to be exactly fun
, as the instances will have different addresses, but what I am looking for is a rename for the point of view of generic coding.
Comment: I find strange that almost everything can be renamed/forwarded, namespaces, types (typedef
) and template types using typedef
, but not functions (or for that matter member functions).
EDIT: For completeness, and since this seems to be the way to do it, here I added a macro to define function aliases:
#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)...);
}
and then you use it like this:
namespace NS1{namepsace NS2{
ALIAS_FUNCTION(NSA::fun, gun); // second argument (target name can't have namespace)
}}
EDIT2: I think exception policy can be incorporated in the alias as well:
#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)...);}
but didn't test it yet.
You must type it three times.
See Question&Answers more detail:
os