Условная компиляция на основе типа переменных #define - PullRequest
0 голосов
/ 25 января 2019

Ниже приводится обрезанная версия того, что я пытаюсь достичь. Я делаю некоторую арифметику со словом, я хотел бы использовать __builtin_clrsb, когда оно доступно, и пользователь использует int как тип слова, иначе компилировать с медленным алгоритмом. Следующие компиляции с __builtin_clrsb независимо от типа WORD.

Код использует C ++ 11, но работает на встроенной системе, поэтому у меня нет доступа к большинству std:: средств.

#if !defined(WORD)
  #define WORD int
#endif

template<size_t S, typename word = WORD>
class my_class {
  ...
  ...
  ...

  size_t do_stuff(){
#if WORD == int && defined(__builtin_clrsb)
    //compile with  __builtin_clrsb
#else
   //comple with slow method
#endif
  }
};

Ответы [ 2 ]

0 голосов
/ 25 января 2019

Я бы сказал, что вы не должны этого делать:

  size_t do_stuff(){
#if WORD == int && defined(__builtin_clrsb)
    //compile with  __builtin_clrsb
#else
    //comple with slow method
#endif
  }

, скорее, вам следует использовать специализацию шаблонов C ++ для решения этой проблемы.

template<class D, size_t S, class word>
struct my_class_do_stuff_impl {
  D& self() { return *static_cast<D*>(this); }
  D const& self() const { return *static_cast<D const*>(this); }
  size_t do_stuff(){
    //compile with slow method
    //use `self()` instead of `this` to access members of `my_class`
  }
};
#if defined(__builtin_clrsb)
  template<class D, size_t S>
  struct my_class_do_stuff_impl<D,S,int> {
    D& self() { return *static_cast<D*>(this); }
    D const& self() const { return *static_cast<D const*>(this); }
    size_t do_stuff(){
      //compile with  __builtin_clrsb
      //use `self()` instead of `this` to access members of `my_class`
    }
  };
#endif
template<size_t S, typename word = WORD>
class my_class:
  public my_class_do_stuff_impl<my_class<S,word>, S, word>
{
  // don't include do_stuff here
  // if you call do_stuff, do this->do_stuff()
};

существует множество причин длясделай это так.Во-первых, WORD, будучи int, не заставляет word в my_class быть int.Другое - то, что мы можем сделать это вне препроцессора, поэтому мы должны.

0 голосов
/ 25 января 2019

Проблема с

#if WORD == int && defined(__builtin_clrsb)

, кроме того факта, что == работает на значениях, а не на типах, в C ++ состоит в том, что #if вычисляется на этапе предварительной обработки, а не на компиляции, ипрепроцессор действительно не знает, что такое int.Правило для #if состоит в том, что после подстановки всех макросов и оценки всех defined() тестов каждый идентифицирующий маркер токен, кроме true, даже ключевое слово C ++, которое не называет макрос, изменяется на 0 в порядкечтобы оценить #if.

Итак, после замены какого-либо другого типа на WORD (скажем, short) и оценки defined как 1, препроцессор остается с

#if short == int && 1

, а затем ключевые слова изменяются на 0:

#if 0 == 0 && 1

, что верно.

Я рекомендую шаблонное решение, показанное в ответ Якка .


[Но на случай, если кому-то все равно, вот взлом на основе препроцессора, который я имел здесь до того, как увидел ответ.Работает только если WORD не содержит пробелов типа long long.]

#define PP_CONCAT1(x,y) x ## y
#define PP_CONCAT(x,y) PP_CONCAT1(x,y)
#define PP_IS_INT_int 1
#define PP_IS_INT_signed 1 /* "signed" alone is the same type as "int" */
#if PP_CONCAT(PP_IS_INT_, WORD) && defined(__builtin_clrsb)
...