gpt4 book ai didi

c++ - 可变参数模板 : how can I check if a specific class is part of the pack, 并在该类存在时执行该类的特定方法

转载 作者:行者123 更新时间:2023-11-30 03:38:29 33 4
gpt4 key购买 nike

考虑以下为 BaseSensor 类提供附加功能的混合。

class PeakSensor{ /*...*/ };
class TroughSensor{ /*...*/ };

template<typename EdgeType> //EdgeType can be PeakSensor or TroughtSensor
class EdgeSensor : public EdgeType
{
public:
void saveEdges(){}
}

class TrendSensor
{
public:
void saveTrends(){}
}

template<typename ... SensorType>
class BaseSensor : public SensorType ... //SensorType can be TrendSensor, EdgeSensor or others...
{
public:
void saveSensor();
}

在哪里

template<typename ... SensorType>
void BaseSensor<SensorType...>::saveSensor()
{
this->saveTrends();
this->saveEdges();
}

和main.cpp

int main(int , const char **) 
{
{ //this works
BaseSensor<EdgeSensor<TroughEdge> , TrendSensor> eps;
eps.saveSensor();
cout << endl;
}

{ //this cannot not find "saveSensorEdges()", so it won't compile
BaseSensor<TrendSensor> eps;
eps.saveSensor();
cout << endl;
}
return 0;
}

我读到解决方案涉及遵循“SFINAE”规则,但是,SO 中的解决方案涉及键入特定于检查成员函数是否有效的代码(例如 here )。是否可以通过检查是否包含混合类(即 TrendSensorEdgeSensor)来最大程度地减少编码?

我正在寻找一种在 c++11 中最小化额外编码的解决方案(即创建多行结构只是为了检查是否存在单个方法)(很可能会使用 boost)。

如果这不可能,我如何检查特定实例的函数是否存在并相应地执行(或不执行)。

基本上,什么都可以放在前面

    EXEC_ONLY_IF_EXISTS ( this->saveTrends(); )
EXEC_ONLY_IF_EXISTS ( this->saveEdges(); )

为了有条件地允许代码并执行它,或者完全删除它取决于混合是否是实例化对象的一部分。谢谢!

最佳答案

您可以调用saveSensor() , 几个新方法:localTrends()localEdges() .

然后,您可以开发 localTrends() 的两个替代实现(选择 SFINAE) ;第一个,那个电话saveTrends() , 仅在 TrendSensor 时启用是实际类的基类,第二个不调用 saveTrends() ,否则(当 TrendSensor 不是基类时)。

localEdges() 的相同策略:两个替代实现(选择 SFINAE),第一个调用 saveEdges() , 仅在 EdgeSensor<Something> 时启用是实际类的基类,第二个不调用 saveEdges() ,否则(当 EdgeSensor<Something> 不是基类时)。

localTrends() 的 SFINAE 选择很简单,使用 std::is_base_of .

localEdges() 的 SFINAE 选择有点复杂,因为你不能(或者至少:我不知道如何)检查是否 EdgeSensor<Something>是使用 std::is_base_of 的实际类的基类因为我不知道 Something EdgeSensor 的模板参数类.

所以我开发了一个模板struct , chkTplInL (对于“checkTemplateInList”)接收“模板模板”参数(即 EdgeSensor 没有其 Something 模板参数)和类型名称列表。这个结构设置了一个 constexpr static bool 值即 true如果基于“模板模板”参数的类(在我们的例子中是 EdgeSensor)在类型名列表中,(在我们的例子中,是:如果 EdgeSensor 类是实际 SensorType 的基础类), false否则。

下面是一个工作示例

#include <type_traits>
#include <iostream>

class PeakSensor { };
class TroughSensor { };
class TroughEdge { };

template<typename EdgeType>
class EdgeSensor : public EdgeType
{ public: void saveEdges(){} };

class TrendSensor
{ public: void saveTrends(){} };

template <template <typename ...> class, typename ...>
struct chkTplInL;

template <template <typename ...> class C>
struct chkTplInL<C>
{ static constexpr bool value = false; };

template <template <typename ...> class C, typename T0, typename ... Ts>
struct chkTplInL<C, T0, Ts...>
{ static constexpr bool value = chkTplInL<C, Ts...>::value; };

template <template <typename ...> class C, typename ... Ts1, typename ... Ts2>
struct chkTplInL<C, C<Ts1...>, Ts2...>
{ static constexpr bool value = true; };

template<typename ... SensorType>
class BaseSensor : public SensorType ...
{
public:
template <template <typename...> class C = EdgeSensor>
typename std::enable_if<
true == chkTplInL<C, SensorType...>::value>::type localEdges ()
{ this->saveEdges(); std::cout << "localEdges case A" << std::endl; }

template <template <typename...> class C = EdgeSensor>
typename std::enable_if<
false == chkTplInL<C, SensorType...>::value>::type localEdges ()
{ std::cout << "localEdges case B" << std::endl; }

template <typename B = TrendSensor>
typename std::enable_if<
true == std::is_base_of<B, BaseSensor>::value>::type localTrends ()
{ this->saveTrends(); std::cout << "localTrends case A" << std::endl; }

template <typename B = TrendSensor>
typename std::enable_if<
false == std::is_base_of<B, BaseSensor>::value>::type localTrends ()
{ std::cout << "localTrends case B" << std::endl; }

void saveSensor ()
{
this->localTrends();
this->localEdges();
}
};


int main ()
{
BaseSensor<EdgeSensor<TroughEdge> , TrendSensor> eps1;
eps1.saveSensor(); // print localTrends case A
// and localEdges case A

BaseSensor<TrendSensor> eps2;
eps2.saveSensor(); // print localTrends case A
// and localEdges case B

BaseSensor<EdgeSensor<TroughSensor>> eps3;
eps3.saveSensor(); // print localTrends case B
// and localEdges case A

BaseSensor<> eps4;
eps4.saveSensor(); // print localTrends case B
// and localEdges case B

return 0;
}

如果你可以使用 C++14 编译器,你可以使用 std::enable_if_t , 所以 SFINAE 选择 localEdges()localTrends()可以简单一点

  template <template <typename...> class C = EdgeSensor>
std::enable_if_t<
true == chkTplInL<C, SensorType...>::value> localEdges ()
{ this->saveEdges(); std::cout << "localEdges case A" << std::endl; }

template <template <typename...> class C = EdgeSensor>
std::enable_if_t<
false == chkTplInL<C, SensorType...>::value> localEdges ()
{ std::cout << "localEdges case B" << std::endl; }

template <typename B = TrendSensor>
std::enable_if_t<
true == std::is_base_of<B, BaseSensor>::value> localTrends ()
{ this->saveTrends(); std::cout << "localTrends case A" << std::endl; }

template <typename B = TrendSensor>
std::enable_if_t<
false == std::is_base_of<B, BaseSensor>::value> localTrends ()
{ std::cout << "localTrends case B" << std::endl; }

关于c++ - 可变参数模板 : how can I check if a specific class is part of the pack, 并在该类存在时执行该类的特定方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39562343/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com