Вопрос о шаблоне Language C++

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

template<typename T>
void
unused(T const &) {
  /* Do nothing. */
}

int main() {
  volatile bool x = false;
  unused(!x); // type of "!x" is bool
}

Как записано ниже, g ++ v3.4.6 компилятор жалуется:

test.cc: In constructor `test::test()':
test.cc:11: error: invalid initialization of reference of type 'const volatile bool&' from expression of type 'volatile bool'
test.cc:3: error: in passing argument 1 of `void unused(const T&) [with T = volatile bool]'

Цель здесь состоит в том, чтобы иметь неиспользованный, подавляют предупреждения неиспользуемой переменной, которые происходят в оптимизированном коде. У меня есть макрос, который делает проверку утверждения, и в оптимизированном коде уходит утверждение, но я хочу, чтобы любые переменные в выражении утверждения остались ссылаемыми так, чтобы я не получал предупреждения неиспользуемой переменной только в оптимизированном коде. В определении для неиспользованного () обрабатывают функцию по шаблону, я использую ссылку так, чтобы никакой код конструктора копии не был непреднамеренно выполнен так, чтобы вызов к неиспользованному мог полностью игнорироваться компилятором.

Для заинтересованных, макрос утверждения похож на это:

#ifdef NDEBUG
#  define Assert(expression) unused(expression)
#else // not NDEBUG
#  define Assert(expression)      \
{         \
  bool test = (expression);      \
     \
  if (!test) {        \
    if (StopHere(__LINE__, __FILE__, __PRETTY_FUNCTION__,  \
                    #expression, false)) {    \
      throw Exit(-1); /* So that destructors are run. */  \
    }         \
  }         \
}
#endif // else not NDEBUG

Для вышеупомянутого тестового сценария я могу совершить ошибку, уходят путем добавления другой подобной неиспользованной функции как это:

template<typename T>
void
unused(T const) {
  /* Do nothing. */
}

Однако затем другие случаи, называющие неиспользованным (), перестали работать из-за неоднозначности, когда аргумент может быть сделан ссылка на с чем-то как:

file.h:176: error: call of overloaded `unused(bool)' is ambiguous
myAssert.h:27: note: candidates are: void unused(T) [with T = bool]
myAssert.h:34: note:                 void unused(const T&) [with T = bool]

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

  1. Вызов к неиспользованному () может быть оптимизирован далеко в не компилятором.
  2. Это вызывает любые переменные, которые присутствуют в выражении, переданном неиспользованному (), чтобы казаться используемыми и таким образом не привести к предупреждению о них определяемый, но не используемые.
  3. Аргумент неиспользованному () может или не мочь ссылаться.
  4. Аргументом неиспользованному () может быть объект с дорогим конструктором копии, который не должен быть вызван, когда неиспользованный () вызывается.

Спасибо.

- William

6
задан WilliamKF 9 January 2010 в 18:42
поделиться

10 ответов

Как сказал Йоханнес в комментариях, вы столкнулись с ошибкой компилятора. Вы можете обойти это, явно преобразовав в bool :

unused( bool( !readWriteActivated) ); // add bool() to any (!volatile_bool_var)

Старый ответ (но все же неплохая идея)

Если я напомню правила квалификации const-volatile, все, что вам нужно, это квалифицировать фиктивная переменная подробнее. По сути, вы просто хотите повторить сообщение об ошибке в объявленном типе: vP.

template<typename T>
void
unused(T const volatile &) { // only change is to add "volatile"
  /* Do nothing. */
}

Также приятно, что вы поместили const после типа, которому он принадлежит.

1
ответ дан 16 December 2019 в 21:40
поделиться

Почему вы передаете ! ReadWriteActivated вместо readWriteActivated , если значение выражения не имеет значения?

-1
ответ дан 16 December 2019 в 21:40
поделиться

Обычный (и гораздо более простой) способ добиться этого - просто привести результат к void .

(void) x;

где x - какое-то другое значение, на которое нет ссылки.

3
ответ дан 16 December 2019 в 21:40
поделиться

Чарльз Николсон предлагает сделать что-то подобное для пометки неиспользуемых переменных по причинам, объясненным в этой статье :

#define UNSUSED(a) ((void)sizeof(a))

Короткая версия... sizeof не оценивает выражение, но компиляторы все равно считают его "использованным", когда его видят в этом контексте.

Я считаю, что это удовлетворяет всем 4 вашим критериям, а именно потому, что sizeof() может принять любое корректное выражение, и потому, что выражение не будет вычислено (и, следовательно, не сгенерирует никакого кода).

2
ответ дан 16 December 2019 в 21:40
поделиться

Измените определение unused:

inline void unused(bool) {}

Поскольку вам уже нужно выражение, для которого требуется преобразование в bool, оно выполняет это преобразование и ничего больше. Inline позволяет компилятору оптимизировать, в том числе в ситуациях, когда выражение не имеет побочных эффектов (но вам нужно будет выполнить тестирование, чтобы точно знать, что происходит в сложных ситуациях).

Кроме того, это устраняет общую проблему с большинством макросов assert: если выражение действительно имеет побочные эффекты, они всегда будут вычисляться. (В зависимости от использования это может быть очень хорошо или очень плохо.)

1
ответ дан 16 December 2019 в 21:40
поделиться

Почему бы вообще не пропустить шаблоны и не использовать многоточия.

inline void unused (...) { /* do nothing */ }
0
ответ дан 16 December 2019 в 21:40
поделиться

Если вы хотите подавить предупреждение о неиспользуемой переменной, почему вы называете ее
. неиспользованный(!readWriteActivated); ? Почему ты не можешь просто назвать это
неиспользуемый(readWriteActivated); и сделайте код как

template<typename T>
void UnUsed(const T& )
{

}

Для более подробных ссылок смотрите запись в блоге от Herb Sutter Here

EDIT: Удалено имя параметра в функции. Это работает для неиспользуемая(!readWriteActivated); а также.

0
ответ дан 16 December 2019 в 21:40
поделиться

Предупреждение компилятора не имеет никакого отношения к используемому или неиспользуемому. Передается переменная volatile - readWriteActivated - в функцию, которая не принимает volatile reference. Попробуйте const cast.

1
ответ дан 16 December 2019 в 21:40
поделиться

Лучшее решение, которое я видел, похоже на это:

#define UNUSED(x) ((void)x)

Это портативно, и подавляет предупреждение успешно.

Редактировать :

Так как вы заявили, что это больше похоже на утверждение, то вы, вероятно, должны сделать что-то вроде этого:

#if defined ASSERT_ENABLED
#define TEST(test) (!(test)) ? assert_failed(# test, __FILE__, __LINE__) : (void)0    
#else
#define TEST(ignore) ((void)0)
#endif

Это даст никакого кода, если assert_enabled определяется и не даст предупреждение о неиспользованных переменных. Это в значительной степени как Assert макрос в LIBC работает.

Я полагаю, что проблема заключается в том, что переменные используются только в утверждении, который является плохим способом делать то, что вы хотите. Почему бы не отметить его как неиспользованным и использовать макрос утверждения в отдельности , таким образом, понятно, что переменная на самом деле не используется для ничего, но вы все равно получите свое утверждение от отладки. Просто решая проблемы индивидуально.

1
ответ дан 16 December 2019 в 21:40
поделиться

Это ошибка:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42655

На уровне unused () нет никакого решения. Вместо этого каждое вхождение можно обойти, введя временную переменную перед вызовом unused ():

template<typename T>
void
unused(T const &) {
  /* Do nothing. */
}

int main() {
  volatile bool x = false;
  bool avoidGCC42655 = !x; // type of "!x" is bool
  unused(avoidGCC42655);
}
0
ответ дан 16 December 2019 в 21:40
поделиться
Другие вопросы по тегам:

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