Understanding this highly templated C++ function binder

☆樱花仙子☆ 提交于 2020-01-13 05:53:32

问题


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 as MemberFunc as a parameter.
  • DeduceImpl returns a BindImpl struct by taking in the function pointer you want to bind.


来源:https://stackoverflow.com/questions/59525502/understanding-this-highly-templated-c-function-binder

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!