考虑以下混合,为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;
}
我已经读到解决方案涉及以下&#34; SFINAE&#34;但是,SO中的解决方案涉及键入特定于检查成员函数是否有效的代码(例如here)。是否可以通过检查mixin类(即TrendSensor
或EdgeSensor
)是否包含在内来最小化编码?
我正在寻找一种最小化额外编码的解决方案(即创建一个多行结构,以检查是否存在单个方法)在c ++ 11中(可以很好地使用boost)。
如果无法做到这一点,我怎么能检查特定实例是否存在该函数并相应地执行它。
基本上,任何事情都可以放在
之前 EXEC_ONLY_IF_EXISTS ( this->saveTrends(); )
EXEC_ONLY_IF_EXISTS ( this->saveEdges(); )
为了有条件地允许代码并执行它,或者完全删除代码取决于mixin是否是实例化对象的一部分。 谢谢!
答案 0 :(得分:2)
您可以在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
(用于&#34; checkTemplateInList&#34;),它们接收一个&#34;模板模板&#34;参数(即EdgeSensor
没有Something
模板参数)和类型名列表。如果基于&#34;模板模板&#34;的类,此结构设置constexpr static
布尔值为true
。参数(EdgeSensor
,在我们的例子中)在类型名列表中,(在我们的例子中,如果EdgeSensor
类是实际SensorType
类的基础),{ {1}}否则。
以下是一个工作示例
false
如果您可以使用C ++ 14编译器,则可以使用#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;
}
,因此std::enable_if_t
和localEdges()
的SFINAE选择可能会更简单
localTrends()