2016-09-18 108 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