2016-01-12 8 views
1

Я хочу, чтобы некоторые функции не вызывались. Давайте проигнорируем случай вызова функции с помощью указателя на функцию или что-то еще, и просто сосредоточимся на случае прямого вызова функции. Я могу сделать это с = delete. Однако диагностика не является достаточно информативной. Я рассмотрел использование static_assert, с помощью которого вы можете предоставить собственное диагностическое сообщение. Я разместил оператор static_assert(false, ...) внутри тела функции, надеясь, что он срабатывает при вызове функции. Однако оказывается, что static_assert не работает, даже если функция не вызывается. Какие-либо предложения?Forbids функции с `static_assert`

Дополнительная информация: Функция запрещена безоговорочно. Таким образом, std::enable_if здесь не применяется. Мотивация для такой функции заключается в том, что я хочу предотвратить определенное использование, которое в противном случае скомпилировалось бы с разрешением перегрузки. Поэтому я не могу просто удалить функцию. deprecated не то, что я хочу. Я хочу ошибку компиляции, а не предупреждение.

+6

Используйте '= delete'. Вот для чего это. –

+0

['static_assert'] (http://en.cppreference.com/w/cpp/language/static_assert) не может остановить функцию от вызова, это цель для утверждений времени компиляции, которая дает ошибки. Вы можете посмотреть, например, ['std :: enable_if'] (http://en.cppreference.com/w/cpp/types/enable_if). –

+2

Почему функция существует, когда она не предназначена для вызова? Просто удалите его из своей кодовой базы. – cdonat

ответ

3

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

static_assert Ионы огня в момент их компиляции. Для обычной функции это время, когда оно анализируется, а не время его вызова. Однако для template это время создания экземпляра. Таким образом, вы можете сделать свою функцию template следующим образом.

template <typename...> 
struct always_false { static constexpr bool value = false; }; 

template <typename... Ts> 
void 
never_call_me(Ts&&...) 
{ 
    static_assert(always_false<Ts...>::value, 
       "You should have never called this function!"); 
} 

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

Трюк, используемый здесь, заключается в том, что always_false<Ts...>::value зависит от параметров типа Ts..., поэтому его нельзя оценить до создания экземпляра template. (Несмотря на то, что мы можем ясно видеть, что он всегда будет false.)

+0

Будет ли 'always_false :: value' и просто' false' внести изменения? – Lingxi

+0

Это действительно имеет значение! Думаю, это было бы решением, которое я хочу. Спасибо :) – Lingxi

+0

Да, трюк заключается в том, чтобы отложить определение условия до тех пор, пока не будут известны аргументы типа. Поскольку 'false' не зависит от параметров, он оценивается сразу. 'always_false :: value', while - well - всегда false, технически все еще зависит от' Ts ... '. – 5gon12eder

2

Если это функция-член, то = delete является вашей лучшей (самой портативной) ставкой. В противном случае, как GCC, так и MSVC имеют поддержку для обозначения функции как «устаревшей», что заставит компилятор выдать предупреждение при вызове функции.

От C++ mark as deprecated:

#ifdef __GNUC__ 
#define DEPRECATED(func) func __attribute__ ((deprecated)) 
#elif defined(_MSC_VER) 
#define DEPRECATED(func) __declspec(deprecated) func 
#else 
#pragma message("WARNING: You need to implement DEPRECATED for this compiler") 
#define DEPRECATED(func) func 
#endif 

Использование:

DEPRECATED(void badidea(int a, const char* b)); 

.... и теперь с C++ 14, мы можем написать:

#define DEPRECATED(func, reason) [[deprecated(reason)]] func 

С использованием:

DEPRECATED(void badidea(int a, const char* b), "This function was a bad idea"); 
+2

Не забывайте [C++ 14 'устаревший атрибут] (http://en.cppreference.com/w/cpp/language/attributes). –

+1

У меня не было. В основном потому, что я не знал, что он существует, чтобы я мог забыть об этом! –

+0

Приятно знать «устаревшую» вещь. Но мне действительно нужна ошибка компиляции, а не предупреждение. – Lingxi