具有模板函数名称的可变参数模板 [英] variadic templates with template function names

查看:172
本文介绍了具有模板函数名称的可变参数模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题,我我试图避免复制粘贴与调用 BaseSensor 的mixins的所有相同命名方法相关的一些代码。

following this question , I am trying to avoid copy-pasting some code related to calling all of the same-named methods of the mixins of the class BaseSensor.

in sensor.hpp

in sensor.hpp

struct EdgeSensor //a mixin
{
    void update(){}
    void printStats() {}
};

struct TrendSensor //another mixin
{
    void update(){}
    void printStats() {}
};

template<typename ... SensorType>
class BaseSensor : public SensorType ... //to my BaseSensor class
{
    void update() /*{ what goes in here??? }*/
    void printStats() /*{ what goes in here??? }*/
};

在sensor.t.hpp

in sensor.t.hpp

template<typename ... SensorType>
void BaseSensor<SensorType...>::update()
{
    int arr[] = { (SensorType::update(), 0)..., 0 };
    (void)arr;
}

template<typename ... SensorType>
void BaseSensor<SensorType...>::printStats()
{
    int arr[] = { (SensorType::printStats(), 0)..., 0 };
    (void)arr;
}

在main.cpp中

int main(int , const char **) 
{
    {
        BaseSensor<EdgeSensor,TrendSensor> ets;
        ets.update();
        ets.printStats();
    }
    {
        BaseSensor<EdgeSensor> ets;
        ets.update();
        ets.printStats();
    }
}

上述代码执行 update(),然后再从所有mixin中执行所有 printStats()

The above code executes the update() of all the mixins in turn, before going on to execute all the printStats() from all the mixins as well.

我想知道是否有可能避免重复执行 BaseSensor :: update() BaseSensor :: printStats()并创建一个通用(模板)函数,接受要在所有mixin中执行的目标函数的名称:

I wonder if it is somehow possible to avoid duplicating the implementation of BaseSensor::update() and BaseSensor::printStats() and create a generic (template) function that accepts the name of the target function to execute across all the mixins:

例如,我可以创建一个方法 runAll()

For example, I could create a method runAll()

template<typename ... SensorType>
class BaseSensor : public SensorType ... //to my BaseSensor class
{
    void update() /*{ what goes in here??? }*/
    void printStats() /*{ what goes in here??? }*/

    template<typename FnName>
    void runAll(FnName f)
    {
        int arr[] = { (SensorType::f(), 0)..., 0 };
        (void)arr;
    }
};

我如何从 BaseSensor :: update code>和 BaseSensor :: printStats()。我尝试使用

void update() { runAll<update>(); }
void printStats() { runAll<printStats>(); }

但这不工作(没想到)。将函数名作为函数参数传递的问题(我看到很多其他问题,例如这里是我不知道如何指向各种 :: update()函数从 BaseSensor :: update ()。例如

but this does not work (did not expect it to). The problem with passing function name as a function argument (which I see is many other questions such as here is that I do not know how to point to various ::update() functions from BaseSensor::update(). for example

void update() { runAll<update>( update() ); }

也不正确。

如果我在哪里将一个工作 runAll()移动到文件sensor.t.hpp中,那么模板参数如何看起来像这样: ?

Is it possible to avoid copying in this case? How would the template parameters look like if I where to move a working runAll() into file "sensor.t.hpp" ?

谢谢

推荐答案

这是一个使用标签调度和非类型模板参数的方法:

Yet another pure c++11 answer which came to my mind. This one uses tag dispatching and non-type template parameters:

template <class T, void (T::*)()>
struct Method { };

template<typename ... SensorType>
class BaseSensor : public SensorType ... //to my BaseSensor class
{
   template <class T, void(T::*M)()>
   int runSingle(Method<T, M>) {
      (this->*M)();
      return 0;
   }

   template <class... Ts>
   void runAll() {
      int run[sizeof...(Ts)] = { runSingle(Ts{})... };
      (void)run;
   }

public:
    void update() {
       runAll<Method<SensorType, &SensorType::update>...>();
    }
    void printStats() {
       runAll<Method<SensorType, &SensorType::printStats>...>();
    }
};

除了折叠表达式(包括skypjack的)将处理一个mixin类的虚拟callee方法...但我认为skypjack的答案可以很容易地修改以实现这样的效果:

It has to be stated though that non of these answers apart from the fold expressions (including skypjack's one) would deal with the virtual callee method of a mixin class... However I think skypjack answer could be easily modified to achieve such an effect:

#include<type_traits>

// (...)

template<typename ... SensorType>
class BaseSensor : public SensorType ...
{
    template<typename F>
    void execute(F &&f) {
        int arr[] = { (f(static_cast<SensorType&>(*this)), 0)..., 0 };
        (void)arr;
    }

public:
    void update() {
        execute([](auto &t) { t.std::remove_reference<decltype(t)>::type::update(); });
    }

    void printStats() {
        execute([](auto &t) { t.std::remove_reference<decltype(t)>::type::printStats(); });
    }
};

这篇关于具有模板函数名称的可变参数模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆