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 55

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

сборка была создана в Компилятор Обозреватель.

вы можете использовать старые добрые макросы

namespace bar
{
    void f();
}

#define f bar::f

int main()
{
    f();
}