Как использовать "using" для функции?

Как использовать "using" для функции? Например

class A;
void f(int);

struct B
{
   using BA = A;
   using Bf = f; ???
};

4 ответов


можно сделать

struct B
{
   using BA = A;
   constexpr static auto Bf = f;
}

таким образом, вам не нужно беспокоиться об указании типа, который может раздражать.

вы не хотите объявлять нестатическую переменную, иначе каждая копия вашего объекта будет нести указатель функции. Вы также не хотите, чтобы он был изменяемым, потому что тогда вы можете переназначить его. Вы также не хотите, чтобы он потенциально определялся во время выполнения, потому что тогда компилятор должен будет доказать себе в данном контексте, что вызов Bf - это действительно вызов f, или еще оплачивают издержки косвенности функции. The constexpr обрабатывает эти последние два пункта.


если f это просто функция, вы можете добавить указатель функции-члена:

void (*Bf)(int) = f;

или просто оберните его в функцию:

void Bf(int i) { f(i); }

вероятно, предпочитают последнее, хотя, поскольку это позволяет избежать добавления дополнительных членов в B.


если f это шаблон функции, вы не можете просто псевдоним, вам нужно будет переслать его:

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

, который является... угу.


ответ Нира Фридмана это здорово, но это не сработает в случае f перегружается.

в C++14 у вас может быть решение для этого с помощью универсальный лямбда:

struct B {
  using BA = A;
  static constexpr auto BF = [](auto&&... args) {
    return f(std::forward<decltype(args)>(args)...);
  };
};

если это кажется немного сложным, это только из-за std::forwardС многословием. Я покажу это без std::forward чтобы сделать его проще понять (но не используйте это, так как это не удастся, если f имеет ссылочные типы как params):

struct B {
  using BA = A;
  static constexpr auto BF = [](auto... args) { return f(args...); };
};

разница в том, что A - это просто тип while f является фактической функцией. Если вы хотите использовать using определение Bf как тип of f, а затем использовать:

using Bf = decltype(f);