Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 具有模板函数名的可变模板_C++_Templates_Variadic Templates - Fatal编程技术网

C++ 具有模板函数名的可变模板

C++ 具有模板函数名的可变模板,c++,templates,variadic-templates,C++,Templates,Variadic Templates,下面的问题是,我试图避免复制粘贴一些与调用类BaseSensor的mixin的所有相同命名方法相关的代码 in sensor.hpp struct EdgeSensor //a mixin { void update(){} void printStats() {} }; struct TrendSensor //another mixin { void update(){} void printStats() {} }; template<typena

下面的问题是,我试图避免复制粘贴一些与调用类
BaseSensor
的mixin的所有相同命名方法相关的代码

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??? }*/
};
那么我如何从
BaseSensor::update()
BaseSensor::printStats()
调用它呢。我试图使用

void update() { runAll<update>(); }
void printStats() { runAll<printStats>(); }
这也不正确

在这种情况下可以避免复制吗?如果我将工作的
runAll()
移动到文件“sensor.t.hpp”中,模板参数会是什么样子


谢谢

您可以使用通用lambda和一种控制反转。
下面是一个简单的工作示例:

#include<iostream>

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 F>
    void execute(F &&f) {
        int arr[] = { (f(static_cast<SensorType&>(*this)), 0)..., 0 };
        (void)arr;
    }

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

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

int main() {
    BaseSensor<EdgeSensor,TrendSensor> ets;
    ets.update();
    ets.printStats();
}
#包括
结构边缘传感器
{

void update(){std::cout如果可以使用c++1z折叠表达式,可能是最短的方法:

template<typename ... SensorType>
class BaseSensor : public SensorType ... //to my BaseSensor class
{
public:
    void update() { (SensorType::update(),...); }
    void printStats() { (SensorType::printStats(),...); }
};
模板
class BaseSensor:public SensorType…//到我的BaseSensor类
{
公众:
无效更新(){(传感器类型::更新(),…);}
void printStats(){(传感器类型::printStats(),…);}
};

另一种
c++11
方法可以是使用指向方法的指针的
std::array
,例如:

template<typename ... SensorType>
class BaseSensor : public SensorType ... //to my BaseSensor class
{
   void runAll(std::array<void (BaseSensor::*)(), sizeof...(SensorType)>&& vs) {
      for (auto v: vs) {
         (this->*v)();
      }
   }

public:
    void update() {
       runAll({&SensorType::update...});
    }
    void printStats() {
       runAll({&SensorType::printStats...});
    }
};
模板
class BaseSensor:public SensorType…//到我的BaseSensor类
{
void runAll(std::array&&vs){
用于(自动v:vs){
(本->*v)();
}
}
公众:
无效更新(){
runAll({&SensorType::update…});
}
void printStats(){
runAll({&SensorType::printStats…});
}
};

我想到了另一个纯粹的c++11答案。这个答案使用标记分派和非类型模板参数:

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>...>();
    }
};
模板
结构方法{};
模板
class BaseSensor:public SensorType…//到我的BaseSensor类
{
模板
int runSingle(方法){
(本->*M)();
返回0;
}
模板
void runAll(){
int run[sizeof…(Ts)]={runSingle(Ts{})…};
(无效)运行;
}
公众:
无效更新(){
runAll();
}
void printStats(){
runAll();
}
};
必须说明的是,除了fold表达式(包括skypjack的一个)之外,这些答案中没有一个会处理mixin类的虚拟被调用方方法……但是我认为skypjack答案可以很容易地修改以达到这样的效果:

#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(); });
    }
};
#包括
// (...)
模板
类BaseSensor:公共传感器类型。。。
{
模板
无效执行(F&&F){
int arr[]={(f(static_cast(*this)),0)…,0};
(无效)arr;
}
公众:
无效更新(){
执行([](auto&t){t.std::remove_reference::type::update();});
}
void printStats(){
执行([](auto&t){t.std::remove_reference::type::printStats();});
}
};

下面是另一个用C++11编译的更紧凑的解决方案:

#include <type_traits>
#include <iostream>

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 <void(SensorType::* ...M)()>
    void run() {
        int arr[] = { 0, ((this->*M)(), 0)... };
        (void)arr;
    }

public:   
    void update() {   
        run<&SensorType::update...>();
    }

    void printStats() {
        run<&SensorType::printStats...>();
    }
};

int main() {
    BaseSensor<EdgeSensor, TrendSensor> bs;
    bs.update();
    bs.printStats();
}
#包括
#包括
结构边缘传感器{

无效更新(){std::cout lambda参数可能应该是一个引用。我看不出普通引用不起作用的原因。
static\u cast
为您提供了该引用。@SamVarshavchik哦,对不起,我刚刚重新阅读了注释。你说的对。你说的是lambda参数。我看错了注释。谢谢你指出它。你好,coul你能纠正我在详细阐述上述方法时的错误吗?你基本上运行一个运行(或准备运行?)的lambda fn
t.update()
。然后是“this”指向lambda函数?lambda的实际执行发生在数组启动期间?@nass我想我不理解这个问题。无论如何,想法是将lambda作为参数传递,让执行器使用正确的类型调用该函数,这样您就不必关心这些类型的数量和类型是的。折叠表达式还没有加入到游戏中。无论如何+1感谢你提到了它们。这在
-std=c++11
g++
上似乎没有运行,我还不能使用更新的标准。@nass是的,它确实需要
-std=c++1z
和gcc,至少在6版中。实际上这很漂亮:)不错,但我会使用
std::array
因为大小是已知的,它不需要分配任何东西:
std::array&&
无论如何,请注意下面的内容。这个版本使用lambda,是使用函子的C++11,并且是这个答案中的版本。看看生成的代码。你注意到了什么?这个版本,即使经过优化,也要昂贵得多。非常有趣确实是我们,但值得一提。;-@W.F.如果你在godbolt上尝试它们,你会发现生成的代码几乎与使用lambdas或functor(当然,一旦优化)一样。事实上非常难以置信。是的。我错过了优化:)我想知道为什么数组版本如此庞大…lambdas的另一个专业人士:)嗨,我们能看看你的解决方案吗?
Method
到底在那里做什么?我怎么解释它呢?我有点困惑:)当然
Method
是一种承载关于单个成员函数的信息…它不存储任何信息,这与中的标记非常相似,但是解决方案不是标记分派,因为它不会通过参数将编译时信息传递给函数(
runAll
),但通过模板参数…
方法
执行有关
SensorType
的信息以及指向成员函数的指针。这可以通过除普通旧类型之外的模板来执行,因为模板可以保存满足要求的非类型参数(它们通常需要静态访问)通过
Method…
我们以双重方式解包
SensorType
包-我们选择
SensorType
本身,让
Method
知道成员函数属于谁,然后我们将指针传递给方法…如果我们可以使用c++17,我们就不必像在那里使用的那样将传感器类型传递给
方法...
template<typename ... SensorType>
class BaseSensor : public SensorType ... //to my BaseSensor class
{
   void runAll(std::array<void (BaseSensor::*)(), sizeof...(SensorType)>&& vs) {
      for (auto v: vs) {
         (this->*v)();
      }
   }

public:
    void update() {
       runAll({&SensorType::update...});
    }
    void printStats() {
       runAll({&SensorType::printStats...});
    }
};
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>...>();
    }
};
#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(); });
    }
};
#include <type_traits>
#include <iostream>

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 <void(SensorType::* ...M)()>
    void run() {
        int arr[] = { 0, ((this->*M)(), 0)... };
        (void)arr;
    }

public:   
    void update() {   
        run<&SensorType::update...>();
    }

    void printStats() {
        run<&SensorType::printStats...>();
    }
};

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