C ++ 11: Как создать псевдоним функции? - PullRequest
61 голосов
/ 26 марта 2012

Если у меня есть класс Foo в строке пространства имен:

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 может эффективно реализовываться как косвенный указатель, тогда как "unaliased" A может использовать "непосредственную семантику".

Ответы [ 7 ]

63 голосов
/ 26 марта 2012

Вы можете определить псевдоним функции (с некоторой работой), используя совершенную пересылку:

template <typename... Args>
auto g(Args&&... args) -> decltype(f(std::forward<Args>(args)...)) {
  return f(std::forward<Args>(args)...);
}

Это решение действительно, даже если f перегружено и / или шаблон функции.

20 голосов
/ 26 марта 2012

Классы типов , поэтому они могут иметь псевдонимы typedef и using (в C ++ 11).

Функции намного больше похожи на объекты , поэтому нет механизма для их псевдонима. В лучшем случае вы можете использовать указатели функций или ссылки на функции:

void (*g)() = &bar::f;
void (&h)() = bar::f;

g();
h();

В том же духе, нет механизма для псевдонимов переменных (если не считать сквозных указателей или ссылок).

15 голосов
/ 26 марта 2012

Абсолютно:

#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
>

Ссылка - это псевдоним существующего объекта.
Я только что создал ссылку на функцию.Ссылка может использоваться точно так же, как и исходный объект.

14 голосов
/ 13 апреля 2018

Указатель функции constexpr может использоваться как псевдоним функции.

namespace bar
{
    int f();
}

constexpr auto g = bar::f;

В месте, где используется псевдоним, компилятор будет вызывать функцию с псевдонимом даже при компиляции без каких-либо оптимизаций.

С GCC7 следующее использование

int main()
{
    return g();
}

становится

main:
  push rbp
  mov rbp, rsp
  call bar::f()  # bar::f() called directly.
  pop rbp
  ret

Сборка была сгенерирована в Проводник компилятора .

9 голосов
/ 18 февраля 2016

Можно ввести функцию в другую область без изменения ее имени. Таким образом, вы можете создать псевдоним функции с другим квалифицированным именем:

namespace bar {
  void f();
}

namespace baz {
  using bar::f;
}

void foo() {
  baz::f();
}
7 голосов
/ 16 июля 2014

Это не стандартный C ++, но большинство компиляторов предоставляют такой способ. С GCC вы можете сделать это:

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

Создает символ f в качестве псевдонима для __f. С VC ++ вы делаете то же самое следующим образом:

#pragma comment(linker, "/export:f=__f")
1 голос
/ 02 ноября 2017

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

namespace bar
{
    void f();
}

#define f bar::f

int main()
{
    f();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...