шаблоны variadic: как я могу проверить, является ли определенный класс частью пакета, и выполнить определенный метод из этого класса, если класс существует

рассмотрите следующие микширования, которые предоставляют дополнительную функциональность 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 включают ввод кода, специфичного для проверки работоспособности функции-члена (например, Вот). Можно ли минимизировать кодирование, проверяя класс mixin (т.е. TrendSensor или же EdgeSensor) включены?

Я ищу решение, которое минимизирует дополнительное кодирование (т.е. создание многострочной структуры, просто чтобы проверить, существует ли один метод) в c ++ 11 (boost может быть очень хорошо использован).

Если это невозможно, как я могу проверить, существует ли функция для конкретного экземпляра и выполнить ее (или нет) соответственно.

В принципе, можно ли что-нибудь поставить перед

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

для того, чтобы условно разрешить код и выполнить его, или вообще удалить его в зависимости от того, является ли mixin частью экземпляра объекта.
благодарю вас!

1

Решение

Вы можете позвонить, в saveSensor()Парочка нового метода: localTrends() а также localEdges(),

Затем вы можете разработать две альтернативные реализации (выбран SFINAE) localTrends(); первый, этот звонок saveTrends(), включается только когда TrendSensor является базовым классом фактического класса, а второй, который не вызывает saveTrends()иначе (когда TrendSensor не базовый класс).

Та же стратегия для localEdges(): две альтернативные реализации (выбран SFINAE), первая, которая вызывает saveEdges(), включается только когда EdgeSensor<Something> является базовым классом фактического класса, а второй, который не вызывает saveEdges()иначе (когда EdgeSensor<Something> не базовый класс).

Выбор SFINAE для localTrends() легко, используя std::is_base_of,

Выбор SFINAE для localEdges() немного сложнее, потому что вы не можете (или, по крайней мере: я не знаю, как) проверить, если EdgeSensor<Something> является базовым классом фактического класса, использующего std::is_base_of потому что я не знаю Something класс, который является аргументом шаблона EdgeSensor,

Итак, я разработал шаблон struct, chkTplInL (для «checkTemplateInList»), которые получают аргумент «шаблон шаблона» (то есть EdgeSensor без его Something шаблон аргумента) и список названий. Эта структура установила constexpr static логическое значение, которое true если класс основан на аргументе «шаблон шаблона» (EdgeSensor, в нашем случае) находится в списке typenames, (что, в нашем случае, это: если 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() может быть немного проще

  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; }
2

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector