ElleSolomina
@ElleSolomina
HedgehogInTheCPP

Возможно ли полное выключение части кода метода шаблонного класса на С++?

Доброго времени суток.


Разрабатываю на С++ довольно давно, особых проблем не испытываю, но вот столкнулся с задачей, которую не понимаю как решить, хотя она должна решаться легко. Подскажите пожалуйста есть ли какой то способ полностью отключить генерацию определённого участка кода в функции шаблона (так, как это было бы при применении препроцессора). Пример:

template <classT, bool alt = false>
Shablon
{

  void foo()
  {
      if (alt)
      {
         ((T*)this)->m_member.foo(); // ошибка компиляции если alt == false, и у класса T нет члена с методом foo.
         ((T*)this)->someFoo();
      }
      ((T*)this)->someFoo2();
  }

}
  • Вопрос задан
  • 4190 просмотров
Решения вопроса 1
skor
@skor
В C++ нельзя так просто взять, чтобы всё было хорошо, если без макросов, конечно. Простое решение с enable_if:

#include <boost/utility/enable_if.hpp>

template <class T, bool alt = false>
struct Shablon
{
  template <bool C>
  typename boost::enable_if_c<C>::type doSomething() {
    ((T*)this)->m_member.foo();
    ((T*)this)->someFoo();
  }

  template <bool C>
  typename boost::disable_if_c<C>::type doSomething() {
  }

  void foo()
  {
    doSomething<alt>();
    ((T*)this)->foo2();
  }
};

Ответ написан
Пригласить эксперта
Ответы на вопрос 6
ixSci
@ixSci
Можно использовать специализацию шаблона, в вашем случае частичную(partial specialization) и там уже писать нужный код. Так как вы хотите(настолько просто) не получится.
Еще можно сделать enable_if на foo функцию внутри одного класса.
Ответ написан
@abby
Мне кажется вам требуется SFINAE, на вики и хабре есть статьи. Советую использовать type_traits. В visual c++ есть __if_exists, но это некроссплатформенно.
Ответ написан
AxisPod
@AxisPod
Глядите в сторону en.cppreference.com/w/cpp/types

Из основных механизмов это: специализации шаблонов и SFINAE.

Проверка наличия метода можно сделать только с помощью SFINAE (enable_if основывается на SFINAE). Вообще проверять наличие метода шаблонами часто может оказаться не самым лучшим решением ибо может быть наследование.

Но вообще гляньте: stackoverflow.com/questions/87372/check-if-a-class-has-a-member-function-of-a-given-signature для конкретной проверки наличия метода.
Ответ написан
@living
В вашем случае можно просто использовать частичную специализацию вашего класса, либо сделать дополнительный шаблонный класс, запускающий требуемые методы, и специализировать только его ( что-то типа такого paste.kde.org/p29e289bb/ ). Можно пойти дальше и использовать SFINAE для определения, есть ли данные методы в членах класса, тогда можно будет спрятать ваш дополнительный параметр шаблона alt.
Ответ написан
Комментировать
sdevalex
@sdevalex
template <int v>
struct Int2Type
{
        enum { value = v };
};

template <classT, bool alt = false>
class Shablon
{
  void doSomething(Int2Type<true>)
  {
     ((T*)this)->m_member.foo();
     ((T*)this)->someFoo();
  }

  void doSomething(Int2Type<false>)
  {
  }

  void foo()
  {
      DoSomething(alt);

      ((T*)this)->someFoo2();
  }
};
Ответ написан
sdevalex
@sdevalex
__
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы