(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)...);
}
template<class A, class B, class C, class = std::enable_if< ... >::type>
), will decltype
transfer the SFINAE in all cases?double& fun(double& x){return x;}
).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.
Is it truly general?
Yes.
Is this the simplest way?
Yes (sadly).
Is this the optimal way? (e.g. can be inlined, no unnecessary copies)
Yes.
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?
Yes, if the expression inside decltype
yields an error (i.e., fun
doesn't exist, perhaps due to SFINAE on fun
), this will trigger SFINAE for gun
aswell, removing it from the overload set.
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;}
).
No, why would it?
Same can be said about member functions, although this has to be done modifying the class I guess.
This isn't a question. What can be said about member functions? All of the above applies equally.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With