75
votes

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

7
@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
@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
@DavidRodríguez-dribeas: Once again, Generated Code. See my second comment above where I define what an alias means. - Andrew Tomazos
@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
@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

7 Answers

74
votes

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.

44
votes

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.

24
votes

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

18
votes

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();
}
15
votes

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.

8
votes

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")
2
votes

You can use good old macros

namespace bar
{
    void f();
}

#define f bar::f

int main()
{
    f();
}