user1899020
user1899020

Reputation: 13575

How to use "using" for a function?

How to use "using" for a function? For example

class A;
void f(int);

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

Upvotes: 7

Views: 836

Answers (4)

G. Sliepen
G. Sliepen

Reputation: 7973

The difference is that A is just a type while f is an actual function. If you want to use using to define Bf as the type of f, then use:

using Bf = decltype(f);

Upvotes: 0

bolov
bolov

Reputation: 75755

Nir Friedman's answer is great, but it won't work in case f is overloaded.

In C++14 you can have a solution for this with a generic lambda:

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

If that seems a bit complicat that is only because of std::forward's verbosity. I will show it without std::forward to make it simpler to grasp (but don't use this as it would fail if f has reference types as params):

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

Upvotes: 2

Barry
Barry

Reputation: 303206

If f is just a function, you could either add a member function pointer:

void (*Bf)(int) = f;

or just wrap it in a function:

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

Probably prefer the latter though, as it avoids adding extra members to B.


If f is a function template, you can't just alias, you'd need to forward to it:

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

which is... yeah.

Upvotes: 2

Nir Friedman
Nir Friedman

Reputation: 17704

You can do

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

That way you don't have to worry about specifying the type, which can be annoying.

You don't want to declare a non-static variable, otherwise every single copy of your object will be carrying around a function pointer. You also don't want it to be mutable, because then you can reassign it. You also don't want it to be potentially determined at runtime, because then the compiler will have to prove to itself in a given context that a call to Bf is really calling f, or else pay function indirection costs. The constexpr handles these last two points.

Upvotes: 11

Related Questions