如何使用 "using" 作为函数?

How to use "using" for a function?

如何使用"using"的功能?例如

class A;
void f(int);

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

如果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)...);
}

这是...是的。

你可以做到

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

这样您就不必担心指定类型,这可能很烦人。

您不想声明一个 non-static 变量,否则您的对象的每个副本都将带有一个函数指针。您也不希望它是可变的,因为这样您就可以重新分配它。您也不希望它在运行时可能被确定,因为编译器必须在给定的上下文中向自己证明对 Bf 的调用实际上是在调用 f,否则就需要支付函数间接费用。 constexpr 处理最后两点。

很好,但如果 f 过载,它就不起作用了。

在 C++14 中,您可以使用 a generic lambda:

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

如果这看起来有点复杂,那只是因为 std::forward 的冗长。我将在没有 std::forward 的情况下展示它,以使其更易于理解(但不要使用它,因为如果 f 具有引用类型作为参数,它将失败):

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

不同之处在于 A 只是一个类型,而 f 是一个实际的函数。如果要使用using定义Bff类型,则使用:

using Bf = decltype(f);