2016-09-18 70 views
-1

以下this问题,我试图避免复制粘贴一些代码相关的调用类BaseSensor类mixins的所有相同名称的方法。可变模板与C++的模板函数名称11

在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

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()之前。

我不知道,如果它是某种能够避免重复的BaseSensor::update()BaseSensor::printStats()实施和创建一个通用的(模板)函数接受目标函数的名称在所有混入执行:

例如,我可以创建一个方法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()BaseSensor::printStats()。我试图用

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

但这不起作用(没想到它)。与传递函数名称作为函数参数(这是我看到的问题是许多其他问题,如here的是,我不知道如何从BaseSensor::update()指向各种::update()功能。例如

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

也是不正确。

在这种情况下是否可以避免复制?可以在单线程中完成,以避免使用C++ 11进行大量复制(即不像使用here那样使用通用lambdas)?模板参数看起来像是在哪里将工作文件runAll()移动到文件“sensor.t.hpp”中?

谢谢。

+4

仅链接答案不好,同样适用于问题。添加相关部分以使自己足够。 – Jarod42

+1

@ Jarod42好的确定 – nass

回答

2

只要函数被称为是两个,你可以使用一个专用结构并依靠超载来解决它。
它遵循最小,工作示例:

#include<iostream> 

struct Executor { 
    template<typename T> 
    static void execute(int, T &t) { 
     t.update(); 
    } 

    template<typename T> 
    static void execute(char, T &t) { 
     t.printStats(); 
    } 
}; 

struct EdgeSensor 
{ 
    void update() { std::cout << "EdgeSensor::update" << std::endl; } 
    void printStats() { std::cout << "EdgeSensor::printStats" << std::endl; } 
}; 

struct TrendSensor 
{ 
    void update() { std::cout << "TrendSensor::update" << std::endl; } 
    void printStats() { std::cout << "TrendSensor::printStats" << std::endl; } 
}; 

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

public: 
    void update() { 
     execute<int>(); 
    } 

    void printStats() { 
     execute<char>(); 
    } 
}; 

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

在你有两个以上的函数被调用的情况下,我想choice伎俩以及适用于这里。

+0

hm仍然有部分(在结构中)需要针对其他类似功能进行复制。它似乎是唯一真正的通用方式是通用lambda表达式... – nass

+2

我会使用一些枚举/标签调度,而不是无信息'char' /'int' – Jarod42

+0

@ Jarod42我也会这样做。从我的角度来看,'int' /'char'技巧比较简洁,就是这样。 – skypjack

1

您仍然可以写(简化的版本)手动通用拉姆达:

void update() { 
    execute([](auto &t) { t.update(); }); 
} 

变得如此

void update() { 
    struct { 
     template <typename T> 
     void operator() (T& t) const { t.update(); } 
    } updater; 
    execute(updater); 
} 
+0

你好,谢谢你的信息。对于复制粘贴它看起来仍然“很长”。理想情况下,我可以以某种方式获得struct“out”,并为't.update()'函数调用提供一个“变量”名称?谢谢 – nass

+0

当你真的介绍_second_函数时,这是非常棘手的。 – skypjack