Ниже приведен небольшой тестовый пример, демонстрирующий проблему, которую я пытаюсь решить с помощью шаблонов в 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]'
Целью здесь является неиспользованное подавление предупреждений о неиспользуемых переменных, которые появляются в оптимизированном коде. У меня есть макрос, который выполняет проверку утверждения, и в оптимизированном коде утверждение исчезает, но я хочу, чтобы любые переменные в выражении утверждения оставались ссылочными, чтобы не получать предупреждения о неиспользуемых переменных только в оптимизированном коде. В определении шаблонной функции unused () я использую ссылку, чтобы код конструктора копирования не запускался непреднамеренно, чтобы компилятор полностью исключил вызов неиспользованного кода.
Для заинтересованных лиц макрос утверждения выглядит следующим образом:
#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. */
}
Однако тогда другие случаи, вызывающие unused (), завершаются неудачно из-за неоднозначности, когда на аргумент можно ссылаться с чем-то вроде:
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]
Итак, мой вопрос: как я могу изменить неиспользованный () или перегрузить его, чтобы он соответствовал следующим требованиям:
- Вызов unused () может быть оптимизирован компилятором до запрета.
- Это приводит к тому, что любые переменные, присутствующие в выражении, передаваемом unused (), представляются использованными и, следовательно, не приводят к предупреждению об их определении, но не использовании.
- На аргумент unused () можно или нельзя ссылаться.
- Аргументом unused () может быть объект с дорогим конструктором копирования, который не должен вызываться при вызове unused ().
Спасибо.
-William