It's easy to create a new name for a type, a variable or a namespace. But how do I assign a new name to a function? For example, I want to use the name holler
for printf
. #define is obvious... any other way?
Solutions:
#define holler printf
void (*p)() = fn; //function pointer
void (&r)() = fn; //function reference
inline void g(){ f(); }
8 Answers 8
There are different approaches:
With C++11 with non-template non-overloaded functions you can simply use:
const auto& new_fn_name = old_fn_name;
If this function has multiple overloads you should use
static_cast
:const auto& new_fn_name = static_cast<OVERLOADED_FN_TYPE>(old_fn_name);
Example: there are two overloads of function
std::stoi
int stoi (const string&, size_t*, int); int stoi (const wstring&, size_t*, int);
If you want to make an alias to the first version you should use the following:
const auto& new_fn_name = static_cast<int(*)(const string&, size_t*, int)>(std::stoi);
Note: there is no way to make an alias to overloaded function such that all its overloaded versions work, so you should always specify which exact function overload you want.
With C++14 you can go even further with
constexpr
template variables. That allows you to alias templated functions:template<typename T> constexpr void old_function(/* args */); template<typename T> constexpr auto alias_to_old = old_function<T>;
Moreover, starting with C++11 you have a function called
std::mem_fn
that allows to alias member functions. See the following example:struct A { void f(int i) { std::cout << "Argument: " << i << '\n'; } }; A a; auto greet = std::mem_fn(&A::f); // alias to member function // prints "Argument: 5" greet(a, 5); // you should provide an object each time you use this alias // if you want to bind an object permanently use `std::bind` greet_a = std::bind(greet, a, std::placeholders::_1); greet_a(3); // equivalent to greet(a, 3) => a.f(3);
6 Comments
constexpr
template variables approach: the alias cannot do type deduction. The compiler requires me to provide template parameter list (I am writing a variadic template function): cannot refer to variable template `alias_to_old' without a template argument listconstexpr auto new_fn_name = old_fn_name
works in C++11 (at least in gcc 4.9.2) and is better than placing &
. It doesn't require call to be always done through pointer and thus allows function to be inlined in place of call.constexpr auto holler = [] ( auto &&...args ) { return printf( std::forward<decltype(args)>( args )... ); };
std::mem_fn
is not an alias since it performs much more magic behind the sense.You can create a function pointer or a function reference:
void fn()
{
}
//...
void (*p)() = fn;//function pointer
void (&r)() = fn;//function reference
5 Comments
fn
, using the alias? Can you explain function pointer & function reference? How are they different? Are they the same here?r();
void (&r)() = this->fn;
typedef int (*printf_alias)(const char*, ...);
printf_alias holler = std::printf;
Should do you fine.
3 Comments
With C++14 generic lambdas, I was able to do the following, which should also work when the target function has multiple overloads:
constexpr auto holler = [] ( auto &&...args ) {
return printf( std::forward<decltype(args)>( args )... );
};
Comments
int (*holler)(const char*, ...) = std::printf;
Comments
Use an inline wrapper. You get both APIs, but keep the single implementation.
Comments
It is worth mentioning here IMO that while the original question (and great answers) are definitely useful if you want to rename a function (there are good reasons to do so!), if all you want to do is strip out a deep namespace but keep the name, there is the using
keyword for this:
namespace deep {
namespace naming {
namespace convention {
void myFunction(int a, char b) {}
}
}
}
int main(void){
// A pain to write it all out every time
deep::naming::convention::myFunction(5, 'c');
// Using keyword can be done this way
using deep::naming::convention::myFunction;
myFunction(5, 'c'); // Same as above
}
This also has the advantage of it being confined to a scope, though you could always use it at the top level of a file. I often use this for cout
and endl
so I don't need to bring in ALL of std
with the classic using namespace std;
at the top of a file, but also useful if you're using something like std::this_thread::sleep_for()
a lot in one file or function, but not everywhere, and not any other functions from the namespace. As always, it's discouraged to use it in .h files, or you'll pollute the global namespace.
This is not the same as the "renaming" above, but is often what is really wanted.
Comments
From fluentcpp : ALIAS_TEMPLATE_FUNCTION(f, g)
#define ALIAS_TEMPLATE_FUNCTION(highLevelF, lowLevelF) \
template<typename... Args> \
inline auto highLevelF(Args&&... args) -> decltype(lowLevelF(std::forward<Args>(args)...)) \
{ \
return lowLevelF(std::forward<Args>(args)...); \
}
void (&NewName)(some_vector&, float, float, float, float) = OldName;
in my next check in.printf
here. That was only an example. The problem here has more to do with limitations of English than anything else. I have a single function serving purpose A and purpose B but I am simply unable to find a single name serving both purposes here.T &a = b;
creates a new name forb
.typedef
for types andnamespace A=B;
for namespaces.using BaseClass::BaseClassMethod
, and there isusing AliasType = Type;
, and there is evennamespace AliasNamespace = Namespace;
. What we are missing isusing AliasFunction = Function;