您可以在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模板参数)和一个类型名列表.如果基于“模板模板”参数(在我们的例子中是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,这样localEdges() 和localTrends() 的 SFINAE 选择可以简单一些
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; }