C++11: как псевдоним функции?
если у меня есть класс Foo в Bar имен:
namespace bar
{
class Foo { ... }
};
тогда я могу:
using Baz = bar::Foo;
и теперь это так же, как я определил класс в моем пространстве имен с именем Baz.
можно ли сделать то же самое для функции?
namespace bar
{
void f();
}
и затем:
using g = bar::f; // error: ‘f’ in namespace ‘bar’ does not name a type
что самый чистый способ сделать это?
решение должно также выполняться для функций шаблона.
определение: если некоторая сущность B Ан псевдоним A, чем если любое или Все использования (не объявления или определения, конечно) A заменены на B в исходном коде, чем (лишенный) сгенерированный код остается тем же самым. Например typedef A B
- это псевдоним. #define B A
- это псевдоним (как минимум). T& B = A
не является псевдонимом, B может эффективно реализовываться как косвенный указатель, где "несмещенный "A может использовать"непосредственную семантику".
7 ответов:
вы можете определить псевдоним функции (с некоторой работой), используя perfect forwarding:
template <typename... Args> auto g(Args&&... args) -> decltype(f(std::forward<Args>(args)...)) { return f(std::forward<Args>(args)...); }
это решение действительно применяется, даже если
f
перегружен и / или шаблон функции.
классы типы, так что они могут быть сглажены с
typedef
иusing
(в C++11).функции гораздо больше похожи на объекты, так что нет никакого механизма для их псевдоним. В лучшем случае вы можете использовать указатели на функции или ссылки на функции:
void (*g)() = &bar::f; void (&h)() = bar::f; g(); h();
в том же духе, нет механизма сглаживания переменные (если не считать сквозных указателей или ссылок).
абсолютно:
#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); }
попробуй:
> g++ a.cpp > ./a.out Test Test Test: 3 >
ссылка-это псевдоним существующего объекта.
Я только что создал ссылку на функцию. Ссылка может использоваться точно так же, как исходный объект.
это не стандартный C++, но большинство компиляторов предоставляют способ сделать это. С GCC вы можете сделать это:
void f () __attribute__ ((weak, alias ("__f")));
это создает символ
f
как псевдоним для__f
. С VC++ вы делаете то же самое таким образом:#pragma comment(linker, "/export:f=__f")
можно ввести функцию в другую область без изменения ее имени. Таким образом, вы можете псевдоним функции с другим полным именем:
namespace bar { void f(); } namespace baz { using bar::f; } void foo() { baz::f(); }
The
constexpr
указатель функции можно использовать как псевдоним функции.namespace bar { int f(); } constexpr auto g = bar::f;
в том месте, где используется псевдоним компилятор будет вызывать функцию aliased даже при компиляции без каких-либо оптимизаций.
С GCC7 следующее использование
int main() { return g(); }
становится
main: push rbp mov rbp, rsp call bar::f() # bar::f() called directly. pop rbp ret
сборка была создана в Компилятор Обозреватель.