首页 > 解决方案 > 了解这个高度模板化的 C++ 函数绑定器

问题描述

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

这段代码是这样调用的:

(typename decltype(::AIpStack::BindPrivate::DeduceImpl(&EthIpIface::driverSendIp4Packet)) ::template Callable<&EthIpIface::driverSendIp4Packet>((this)).toFunction())

我试图了解这段代码的作用。它显然是将函数指针(如&EthIpIface::driverSendIp4Packet)绑定到某物的一种方法。

上面的行来自这个宏,它填充这个结构成员,如果有人感兴趣的话。您可能想在 Function 中获得战利品

我不明白的第一部分是

template<Ret (Container::*MemberFunc)(Args...)>

对我来说 atemplate必须跟在后面typename。此外,typename 后面的内容是要替换的内容。我看不到这个模板如何使 Callable 模板化。我不知道something去 哪里Callable<something>

还有,什么是DeduceImpl?看起来像一个函数声明,但没有定义。

还有,什么Container::*MemberFunc意思?

标签: c++c++17

解决方案


首先,模板也可以接受非类型参数以及 typename 和 class。在这种情况下:

template<Ret (Container::*MemberFunc)(Args...)>

这是一个将函数指针作为参数的模板,其中Ret返回类型Container::*MemberFunc是指向Container具有Args...引用可变参数的特定成员函数的指针。这为指针提供了标识符MemberFunc。我感觉范围解析运算符后面的星号让您感到困惑,因为如果您在任何其他情况下将这两者一起使用,通常您会收到编译器错误,但在这种特定情况下, 这两个被认为是::*代表这种模板参数的一个标记两个::*


对于这一行:

BindImpl<Container, Ret, Args...> DeduceImpl (Ret (Container::*)(Args...));

它是一个函数声明。这是一个名为的函数DeduceImpl,它将返回一个BindImpl将函数指针作为参数的结构。我推断这个函数是你绑定函数指针的接口,因此(可能)缩短的名称“演绎实现”和“绑定实现”从我读过的内容来看,这个函数仅用于 decltype,所以这个函数没有实际的定义。


关于该模板在这一行中的实际使用方式(重新格式化以便于阅读):

typename decltype(::AIpStack::BindPrivate::DeduceImpl(&EthIpIface::driverSendIp4Packet))
::
template Callable<&EthIpIface::driverSendIp4Packet>(this).toFunction()

这是一个模板消歧器,只是为了让编译器知道正在使用实际模板而不是小于比较运算符。

您不会为了使用模板而编写所有这些内容。写这行可能是因为它是在项目中实例化模板的少数几种方式之一。


总之:

  • template<Ret (Container::*MemberFunc)(Args...)>是一个模板,它接受一个称为MemberFunc参数的函数指针。
  • DeduceImplBindImpl通过接收要绑定的函数指针返回一个结构。

推荐阅读