可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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".
回答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.
回答2:
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).
回答3:
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.
回答4:
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")
回答5:
The constexpr
function pointer can be used as a function alias.
namespace bar
{
int f();
}
constexpr auto g = bar::f;
In the place where the alias is used the compiler will call the aliased function even when compiling without any optimizations.
With GCC7 the following usage
int main()
{
return g();
}
becomes
main:
push rbp
mov rbp, rsp
call bar::f() # bar::f() called directly.
pop rbp
ret
The assembly was generated in Compiler Explorer.
回答6:
It is possible to introduce the function into a different scope without changing its name. So you can alias a function with a different qualified name:
namespace bar {
void f();
}
namespace baz {
using bar::f;
}
void foo() {
baz::f();
}
回答7:
You can use good old macros
namespace bar
{
void f();
}
#define f bar::f
int main()
{
f();
}