问题
template<typename Container, typename Ret, typename ...Args>
struct BindImpl {
template<Ret (Container::*MemberFunc)(Args...)>
class Callable {
public:
inline constexpr Callable (Container *container) :
m_container(container)
{}
inline Ret operator() (Args ...args) const
{
return (m_container->*MemberFunc)(std::forward<Args>(args)...);
}
inline Function<Ret(Args...)> toFunction() const
{
return Function<Ret(Args...)>(*this);
}
private:
Container *m_container;
};
};
template<typename Container, typename Ret, typename ...Args>
BindImpl<Container, Ret, Args...> DeduceImpl (Ret (Container::*)(Args...));
This code is called like this:
(typename decltype(::AIpStack::BindPrivate::DeduceImpl(&EthIpIface::driverSendIp4Packet)) ::template Callable<&EthIpIface::driverSendIp4Packet>((this)).toFunction())
I'm trying to understand what this code does. It apprently is a way to bind function pointers (like &EthIpIface::driverSendIp4Packet
) to something.
The line above is from this macro, which fills this struct member, if anyone is intersted. You may wanna have a loot at Function.
The first part that I don't understand is
template<Ret (Container::*MemberFunc)(Args...)>
For me a template
must be followed by typename
. Also, what follows typename, is the thing to be substituted for. I don't see how this template makes Callable templated. I don't know where something
goes to in Callable<something>
.
Also, what is DeduceImpl
? Looks like a function declaration but without a definition.
Also, what Container::*MemberFunc
means?
回答1:
Firstly, templates can also take in non-type parameters as well as with typename and class. In this case:
template<Ret (Container::*MemberFunc)(Args...)>
This is a template taking a function pointer as a parameter, where Ret
is the return type, Container::*MemberFunc
is the pointer to a specific member function in Container
with Args...
referencing variadic arguments. This gives the pointer the identifier MemberFunc
. I have a feeling the asterisk following the scope resolution operator confused you, as usually you would receive a compiler error if you used these two together in any other situation but in this specific case these two are considered one token ::* representing this kind of template parameter instead of the two ::
and *
.
For this line:
BindImpl<Container, Ret, Args...> DeduceImpl (Ret (Container::*)(Args...));
It is a function declaration. This is a function named DeduceImpl
that will return a BindImpl
struct that takes a function pointer as an argument. I'm inferring that this function is the interface by which you bind the function pointer, hence the (probably) shortened names "Deduce Implementation" and "Bind Implementation" From what I've read, this function is only used for decltype, so there's no actual definition for this function.
For how this template is actually being utilized in this line (reformatted for easier reading):
typename decltype(::AIpStack::BindPrivate::DeduceImpl(&EthIpIface::driverSendIp4Packet))
::
template Callable<&EthIpIface::driverSendIp4Packet>(this).toFunction()
This translates to meaning (more or less):
For the specific kind of BindImpl
that would hold the function pointer to driverSendIp4Packet()
, create an explicit instantiation of the Callable
member function toFunction()
.
It's a mouthful just to basically say you're using an explicit instantiation of toFunction()
that runs driverSendIp4Packet()
.
You wouldn't write all of this just to use the template. This line was probably written because it's one of the few ways the template is instantiated in the project.
In summary:
template<Ret (Container::*MemberFunc)(Args...)>
is a template that takes a function pointer referred to asMemberFunc
as a parameter.DeduceImpl
returns aBindImpl
struct by taking in the function pointer you want to bind.
来源:https://stackoverflow.com/questions/59525502/understanding-this-highly-templated-c-function-binder