C++11: How to alias a function?
Solution 1
You can define a function alias (with some work) using perfect forwarding:
template <typename... Args>
auto g(Args&&... args) -> decltype(f(std::forward<Args>(args)...)) {
return f(std::forward<Args>(args)...);
}
This solution does apply even if f
is overloaded and/or a function template.
Solution 2
The constexpr
function pointer can be used as a function alias.
namespace bar
{
int f();
}
constexpr auto g = bar::f;
It is highly likely (but not guaranteed by the language) that using g
uses bar::f
directly.
Specifically, this depends on compiler version and optimization level.
In particular, this is the case for:
- GCC 4.7.1+, without optimization,
- Clang 3.1+, without optimization,
- MSVC 19.14+, with optimization.
See assembly generated by these compilers.
Solution 3
Classes are types, so they can be aliased with typedef
and using
(in C++11).
Functions are much more like objects, so there's no mechanism to alias them. At best you could use function pointers or function references:
void (*g)() = &bar::f;
void (&h)() = bar::f;
g();
h();
In the same vein, there's no mechanism for aliasing variables (short of through pointers or references).
Solution 4
It's possible to introduce the function into a different scope without changing its name. That means that you can alias a function with a different qualified name:
namespace bar {
void f();
}
namespace baz {
using bar::f;
}
void foo() {
baz::f();
}
Solution 5
Absolutely:
#include <iostream>
namespace Bar
{
void test()
{
std::cout << "Test\n";
}
template<typename T>
void test2(T const& a)
{
std::cout << "Test: " << a << std::endl;
}
}
void (&alias)() = Bar::test;
void (&a2)(int const&) = Bar::test2<int>;
int main()
{
Bar::test();
alias();
a2(3);
}
Try:
> g++ a.cpp
> ./a.out
Test
Test
Test: 3
>
A reference is an alias to an existing object.
I just created a reference to a function. The reference can be used in exactly the same way as the original object.

Andrew Tomazos
Updated on July 12, 2022Comments
-
Andrew Tomazos 4 months
If I have a class Foo in namespace bar:
namespace bar { class Foo { ... } };
I can then:
using Baz = bar::Foo;
and now it is just like I defined the class in my namespace with the name Baz.
Is it possible to do the same for functions?
namespace bar { void f(); }
And then:
using g = bar::f; // error: ‘f’ in namespace ‘bar’ does not name a type
What is the cleanest way to do this?
The solution should also hold for template functions.
Definition: If some entity B is an alias of A, than if any or all usages (not declarations or definitions of course) of A are replaced by B in the source code than the (stripped) generated code remains the same. For example
typedef A B
is an alias.#define B A
is an alias (at least).T& B = A
is not an alias, B can effectively implemented as an indirect pointer, wheres an "unaliased" A can use "immediate semantics". -
Andrew Tomazos over 10 yearsSo what is going on here then:
auto g = bar::f;
? -
Kerrek SB over 10 years@user1131467: You declare and define a new object.
-
Andrew Tomazos over 10 yearsWhat is the type of that object? And what is going on here:
inline void g() { bar::f(); }
-
Kerrek SB over 10 yearsBashphorism 2 alert?! That last one defines an entirely new function.
-
Andrew Tomazos over 10 yearsWhat's bashphorism 2? No wait, why is the sky blue? No wait, why is steam coming out your ears? No wait, why are you picking up that axe?
-
Ben Voigt over 10 yearsWhen defining aliases, I usually like to see them made
const
. Otherwise a great workaround. This still is quite different from using, however, because it neither pulls in multiple overloads, nor overloads with already-visible definitions with the same name. -
Admin over 10 yearsIIRC, function references work better than function pointers. (but it's been a while since I was playing with this, and I don't know if function references are portable either)
-
Kerrek SB over 10 years@Hurkyl: There's no real difference between function references and pointers, as the former always immediately decay into the latter. You can say
foo()
,(*foo)()
and(**foo)()
as much as you like. -
R. Martinho Fernandes over 10 yearsIt doesn't apply if
f
is a function template that can't use type deduction. -
Andrew Tomazos over 10 years@R.MartinhoFernandes: Can you provide an example of such a function template that can't use type deduction?
-
R. Martinho Fernandes over 10 years@user1131467 Any function that uses a template argument to determine its return type (like
boost::lexical_cast
), or uses a template argument as a de facto argument (likestd::get
). -
Andrew Tomazos over 10 yearsDoesn't this require an extra dereference when alias is called? Also how does this work for template functions?
-
Martin York over 10 yearsAS you can see it works fine. With templates it works for specific instantiations you can not alias a template but you can alias a specific version of a template.
-
Admin over 10 years@Kerrek: I recall seeing performance differences when I was testing it. Unfortunately, I cannot recall what precise variations I was experimenting with.
-
Johannes Schaub - litb over 10 years@Kerrek if you say
&foo
, then you get the address of the function pointer instead of the function. Iffoo
is a reference, this would work correctly and yield the address of the function. -
Kerrek SB over 10 years@JohannesSchaub-litb: It's true that there's a function reference somewhere, but it decays to a function pointer very easily, to the extend that you can keep dereferencing, as each reference immediately decays to a pointer again.
-
Johannes Schaub - litb over 10 years@RMartin if it would assume "ExplicitArgs" to be empty if you don't specify it could rewrite it to
template<typename ...ExplicitArgs, typename ...Args> void foo(Args...args)
and call the other one likef<ExplicitArgs...>(args...)
. Unfortunately it only does the "assume-to-be-empty" for a trailing template parameter pack, and not for the one-before-trailing one. -
Johannes Schaub - litb over 10 years@KerrekSB I am saying that if you have
void f(); void (&rf)() = f;
then both&f
and&rf
yield the address off
. But ifrf
would be a function pointer,void (*rf)() = f;
, then&rf
returns its address rather than that of the function, which is bad. -
Johannes Schaub - litb over 10 years@RMartin actually GCC and Clang already do exactly that, so that the above ExplicitArgs way even works in the wild! They consider both template parameter packs "trailing".
-
Kerrek SB over 10 years@JohannesSchaub-litb: oh, now I get it. Yes, you're right, references are better in that regard.
-
Richard Smith over 10 yearsA better idiom for this is:
constexpr auto &alias = Bar::test;
. Theconstexpr
part guarantees that the reference will be substituted at compile-time. Theauto
part won't work for a templated function, though. -
Steve Jessop over 8 years"A reference is an alias to an existing object. I just created a reference to a function." -- and functions are not objects. So references-to-function are not an alias to an existing object (just as function pointers are not object pointers) :-)
-
Martin York over 8 years@SteveJessop: What is an object? Is it not something that takes up space in memory? A function occupies space in memory and has an address. So why is it not an object? (At a conceptual level (probably not a language level)).
-
Steve Jessop over 8 years@LokiAstari: OK, if you want to use "object" to mean something conceptual, that's different from what it says it means in the standard, that's fine I guess. It will cause confusion among people like me, though who are used to using the language-level definition when talking about C++ :-)
-
Martin York over 8 years@SteveJessop: I was trying to use the language level definition. But obviously (as you state) function does not fit that definition in C++. But alias is not a part of the language definition either. Have you a suggestion for better wordage of the above?
-
Steve Jessop over 8 years@LokiAstari: I think I've seen "entity" used to mean, roughly, "an object, function, class or member". But of course you can't take a reference to a class, and there's no reference-to-member either. So unfortunately the best term I can think of that's precise, is "object or function". Anyway the questioner is (it turns out) using a special meaning of "alias" and it's not necessarily true that a reference is an alias by that definition, although sometimes it is...
-
einpoklum over 6 yearsAnd will this work with overloaded functions, templates, everything?
-
Dennis about 6 yearsI don't know why this isn't the accepted answer: I just tried it and it works, even for template functions (without needing to be prefixed with template <typename> to do so). As far as I can tell it pulls in all of the overloads for the name.
-
Tom about 6 years@einpoklum Yes - ish. You can make the compiler emit an alias for any concrete function that it generates - they're just entry points in an executable object with names assigned to them, after all. Overloaded functions are just functions, with the name mangled to reflect the function signature. Template functions don't have executable names themselves, but instantiations of those template functions do - and the compiler can emit aliases for them. Whether it's much use to you is another matter.
-
davmac about 6 yearsOne difficulty with this is that you must use the mangled symbol name for the function in the
alias( )
declaration. Your example looks wrong (for this reason); or even if it's correct on some system, it will be much more complicated for a function with parameters.. -
Tom about 6 years@Davmac: only if you want the alias to be a mangled name. There is nothing wrong with creating an unmangled alias, though it will be of more use from languages other than C++.
-
davmac about 6 years@Tom I'm not saying the alias will be mangled (or not). It is the symbol that you want to alias to that is problematic. If it is mangled then you must use the mangled name to create the alias. The question asks about creating an alias for
bar::foo
so you would have to use the mangled name of that symbol when creating the alias. Eg it won't be "__foo", more like "_ZN3bar3fooEv". -
Tom about 6 yearsAh, yes, true in VC++. The GCC method doesn't require you to name the original symbol, though.
-
davmac about 6 years@Tom, yes it does. That's what the "__f" (which should be "_ZN3bar3fooEv") is.
-
Johannes Jendersie about 5 yearsThe correct and shorter answer which also avoids the problems of
ExplicitArgs
is given by Jason Haslam below! -
Michał Fita about 5 years@RichardSmith you should convert that comment to an answer - it's great!
-
ricab over 4 yearsThis drops noexcept information and so is not a precise alias in C++17 anymore: coliru.stacked-crooked.com/a/f3ee222a98c97184
-
JVD over 4 yearsThis is the best solution, but does not work for inlines: namespace bar { static inline __attribute__((always_inline)) void f(); } namespace baz { using bar::f; } void foo() { baz::f(); } $ g++ -g -std=gnu++11 -x c++ -Wall -Wextra -c tns.C x.C:3:8: warning: inline function 'void bar::f()' used but never defined void f(); ^ tns.C: In function 'void foo()': tns.C:3:8: error: inlining failed in call to always_inline '...': function body not available x.C:11:11: error: called from here baz::f();
-
JVD over 4 yearsnamespace bar { static inline __attribute__((always_inline)) void f(); } namespace baz { using bar::f; } void foo() { baz::f(); }
-
Ignitor about 3 yearsThis can have very unexpected effects depending on the name of the macro. See this answer for reasons (especially the "Macros have no namespace" is dangerous here).
-
Mariusz Jaskółka over 2 yearsThis is the best answer, but you should add that this is not a real alias - compiler actually is allowed to not inline the function call and make a real call. But I believe most compilers will optimize it out, like Compiler Explorer shown.
-
Mariusz Jaskółka over 2 yearsMacros are old, but nowhere near good in C++.
-
Mariusz Jaskółka over 2 yearsThis answer is partially wrong - it is only a workaround for lack of function aliases in C++. What is more, calling
g
instead off
may break the ABI, especially if bothf
andg
are a strong symbols. -
Tom over 2 yearsYep, quite right; in my GCC 9.2.1 this is
void f() __attribute__ ((weak, alias("_ZN3bar1fEv")));
-
Unicorn over 2 yearsYou need to take care when using macroses obviously. Every decent C++ programmer knows that. I would not recommend to define such a macro in a header. But in source file it should be fine. With macroses you can always shoot yourself in the foot. If your technology stack permits you probably should use Paweł Bylica's answer. But for older compilers you can consider this solution to ease your life a little bit.
-
Paweł Bylica over 2 years@jaskmar, I updated the answer assuming you meant indirect/direct call instead of inlining. Inlining is not relevant here.
-
Prolight over 2 yearsHow do I use this?