90

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
  • 66,139
  • 40
  • 186
  • 319
  • what is it that you want to achieve? If you state what you actually need it might be possible to provide alternatives, but as it is, it is not even clear what you mean by *alias* – David Rodríguez - dribeas Mar 25 '12 at 22:12
  • 1
    @DavidRodríguez-dribeas: There is little confusion over what "alias" means in the above. In general if B is an alias of A, than if you replace usages of A with B, than the generated code remains unchanged. Why you would want this is also straightforward. I want to give a library function a second name/namespace. I suspect the cleanest way is to just wrap a call to the old name with an always_inline function of the new name. The wrapper will be compiled out, leaving something indistinguishable from a direct call to the old name, as desired. – Andrew Tomazos Mar 25 '12 at 23:47
  • Well, it is still not clear, for example, whether a function pointer defined in the destination namespace meets your requirements or not. It is not the same function but your program can go along without ever noticing (there are situations where it matters, but they are not that common). Additionally, you did not state whether you need a different name or just a different namespace, so a *using-declaration* could also meet your needs... Remember to ask about what you need, as that is what enables uses of different alternatives that might not exactly fit your textual description. – David Rodríguez - dribeas Mar 26 '12 at 11:49
  • 1
    @DavidRodríguez-dribeas: A function pointer would produce different code than a normal function call as the function pointer needs to be dereferenced before the call. – Andrew Tomazos Mar 26 '12 at 15:44
  • Do you mean c++ code or the generated code? On the C++ side, source code, the function will be automatically be dereferenced, in the generated binary it will be different. That is why it is important to state your **requirements**, which is what I am trying to get through: state the **requirements**. – David Rodríguez - dribeas Mar 26 '12 at 15:56
  • 1
    @DavidRodríguez-dribeas: Once again, __Generated Code__. See my second comment above where I define what an alias means. – Andrew Tomazos Mar 26 '12 at 16:09
  • We are having quite a bit of misunderstanding. I am probably not being as clear as I wanted, but let's try again: When you *ask* a question you should make clear what your *requirements* are. Not as a comment, but rather as part of the *question*, there are some things that seem obvious to you (*alias* == same generated code) that are not clear as *alias* does not have a precise definition --of which I provided other possible interpretations. Also note that the solution that you seem to prefer does not guarantee the same exact binary code. – David Rodríguez - dribeas Mar 26 '12 at 17:30
  • 1
    @DavidRodríguez-dribeas: Under what circumstances would the solution of wrapping the function call in an inline function not produce the same generated code? – Andrew Tomazos Mar 26 '12 at 18:24
  • `inline` does not force inlining, only *suggests*. Even if you force inlining through compiler specifics, the compiler might generate a non-inline version of the wrapper (gcc does, even when not used --i.e. the address is not taken-- in code) – David Rodríguez - dribeas Mar 26 '12 at 18:50
  • 1
    @DavidRodríguez-dribeas: As I said "always_inline" refering to the attribute(s) that force inlining. See section __6.39 An Inline Function is As Fast As a Macro__ in the GCC manual. – Andrew Tomazos Mar 26 '12 at 18:53
  • 1
    This doesn't answer your question given *current* C++, but if/when the "Generalizing alias declarations" proposal p0945r0 is accepted, you will be able to say exactly that, `using g = bar::f;`.http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0945r0.html (http://wg21.link/p0945r0) – Dwayne Robinson Jan 29 '20 at 02:51

7 Answers7

79

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.

Jeremiah Willcock
  • 30,161
  • 7
  • 76
  • 78
  • 4
    It doesn't apply if `f` is a function template that can't use type deduction. – R. Martinho Fernandes Mar 25 '12 at 23:07
  • @R.MartinhoFernandes: Can you provide an example of such a function template that can't use type deduction? – Andrew Tomazos Mar 25 '12 at 23:49
  • 3
    @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 (like `std::get`). – R. Martinho Fernandes Mar 26 '12 at 00:06
  • 3
    @RMartin if it would assume "ExplicitArgs" to be empty if you don't specify it could rewrite it to `template void foo(Args...args)` and call the other one like `f(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 Mar 26 '12 at 18:41
  • 2
    @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". – Johannes Schaub - litb Mar 26 '12 at 18:49
  • 1
    The correct and shorter answer which also avoids the problems of `ExplicitArgs` is given by [Jason Haslam](https://stackoverflow.com/a/35467761/1913512) below! – Johannes Jendersie Sep 14 '17 at 09:34
  • 5
    This drops noexcept information and so is not a precise alias in C++17 anymore: http://coliru.stacked-crooked.com/a/f3ee222a98c97184 – ricab Mar 26 '18 at 18:55
  • 1
    This answer is partially wrong - it is only a workaround for lack of function aliases in C++. What is more, calling `g` instead of `f` may break the ABI, especially if both `f` and `g` are a strong symbols. – Mariusz Jaskółka Mar 23 '20 at 13:24
  • 2
    How do I use this? – Prolight Jun 06 '20 at 20:05
59

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.

Paweł Bylica
  • 3,780
  • 1
  • 31
  • 44
  • This 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 Mar 23 '20 at 13:15
  • 2
    @jaskmar, I updated the answer assuming you meant indirect/direct call instead of inlining. Inlining is not relevant here. – Paweł Bylica Apr 06 '20 at 09:59
  • Nice solution. But it does not work for template and overloaded functions. – anton_rh Feb 15 '23 at 13:27
27

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).

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • So what is going on here then: `auto g = bar::f;` ? – Andrew Tomazos Mar 25 '12 at 21:21
  • 1
    @user1131467: You declare and define a new object. – Kerrek SB Mar 25 '12 at 21:21
  • 1
    What is the type of that object? And what is going on here: `inline void g() { bar::f(); }` – Andrew Tomazos Mar 25 '12 at 21:22
  • 2
    Bashphorism 2 alert?! That last one defines an entirely new function. – Kerrek SB Mar 25 '12 at 21:25
  • What'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? – Andrew Tomazos Mar 25 '12 at 21:33
  • When 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. – Ben Voigt Mar 25 '12 at 21:43
  • IIRC, 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) –  Mar 25 '12 at 22:04
  • 1
    @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. – Kerrek SB Mar 25 '12 at 23:05
  • @Kerrek: I recall seeing performance differences when I was testing it. Unfortunately, I cannot recall what precise variations I was experimenting with. –  Mar 26 '12 at 05:59
  • @Kerrek if you say `&foo`, then you get the address of the function pointer instead of the function. If `foo` is a reference, this would work correctly and yield the address of the function. – Johannes Schaub - litb Mar 26 '12 at 18:17
  • 1
    @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. – Kerrek SB Mar 26 '12 at 18:25
  • 3
    @KerrekSB I am saying that if you have `void f(); void (&rf)() = f;` then both `&f` and `&rf` yield the address of `f`. But if `rf` 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 Mar 26 '12 at 18:42
  • @JohannesSchaub-litb: oh, now I get it. Yes, you're right, references are better in that regard. – Kerrek SB Mar 26 '12 at 19:26
21

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();
}
Jason Haslam
  • 2,617
  • 13
  • 19
  • I 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 to do so). As far as I can tell it pulls in all of the overloads for the name. – Dennis Sep 29 '16 at 20:24
  • This 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 Apr 01 '18 at 11:51
  • namespace bar { static inline __attribute__((always_inline)) void f(); } namespace baz { using bar::f; } void foo() { baz::f(); } – JVD Apr 01 '18 at 11:58
  • This does not answer the question because you can't give the function a different name. `f` remains `f`, even though it is in different namespace. Using function under different name is what alias is supposed to be. – anton_rh Feb 15 '23 at 13:21
  • Also, you can't use this solution for static functions inside class. Only for functions inside namespaces. This is not required in the question. But I need this anyway. – anton_rh Feb 15 '23 at 13:24
16

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.

Martin York
  • 257,169
  • 86
  • 333
  • 562
  • Doesn't this require an extra dereference when alias is called? Also how does this work for template functions? – Andrew Tomazos Mar 26 '12 at 00:44
  • AS 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. – Martin York Mar 26 '12 at 00:58
  • 11
    A better idiom for this is: `constexpr auto &alias = Bar::test;`. The `constexpr` part guarantees that the reference will be substituted at compile-time. The `auto` part won't work for a templated function, though. – Richard Smith Mar 27 '12 at 05:36
  • 1
    "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) :-) – Steve Jessop Feb 19 '14 at 22:44
  • @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)). – Martin York Feb 20 '14 at 17:24
  • @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++ :-) – Steve Jessop Feb 20 '14 at 17:34
  • @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? – Martin York Feb 20 '14 at 22:50
  • @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... – Steve Jessop Feb 21 '14 at 01:54
  • 1
    @RichardSmith you should convert that comment to an answer - it's great! – Michał Fita Nov 03 '17 at 10:17
8

It's not standard C++, but most compilers provide a way of doing this. With GCC you can do this:

void f () __attribute__ ((weak, alias ("__f")));

This creates the symbol f as an alias for __f. With VC++ you do the same thing this way:

#pragma comment(linker, "/export:f=__f")
Tom
  • 7,269
  • 1
  • 42
  • 69
  • And will this work with overloaded functions, templates, everything? – einpoklum Apr 27 '16 at 20:40
  • @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. – Tom Oct 03 '16 at 10:28
  • One 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.. – davmac Oct 17 '16 at 11:19
  • @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++. – Tom Oct 17 '16 at 11:26
  • @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". – davmac Oct 17 '16 at 11:46
  • Ah, yes, true in VC++. The GCC method doesn't require you to name the original symbol, though. – Tom Oct 17 '16 at 11:47
  • @Tom, yes it does. That's what the "__f" (which should be "_ZN3bar3fooEv") is. – davmac Oct 17 '16 at 11:48
  • Yep, quite right; in my GCC 9.2.1 this is `void f() __attribute__ ((weak, alias("_ZN3bar1fEv")));` – Tom Mar 23 '20 at 13:52
2

You can use good old macros

namespace bar
{
    void f();
}

#define f bar::f

int main()
{
    f();
}
Unicorn
  • 1,397
  • 1
  • 15
  • 24
  • 1
    This can have very unexpected effects depending on the name of the macro. See [this answer](https://stackoverflow.com/a/14041847/490560) for reasons (especially the "Macros have no namespace" is dangerous here). – Ignitor Aug 14 '19 at 14:17
  • Macros are old, but nowhere near good in C++. – Mariusz Jaskółka Mar 23 '20 at 13:17
  • You 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. – Unicorn Mar 23 '20 at 18:45