#c #if-statement
Вопрос:
Даже имея много вопросов по этой теме, у меня возникает все больше и больше проблем. Я думаю, что проблема в понимании значения определенных слов. Все приведенные ниже цитаты взяты из Cppreference
- Что означает «отброшено» в приведенном ниже тексте? Я понимаю «отброшенный» как что-то, что никогда не компилировалось/не трогалось, что-то, что, чем бы это ни было (например, случайные символы, которые были бы ошибками), не будет вмешиваться в остальную часть программы.
В инструкции constexpr if значение условия должно быть контекстуально преобразованным постоянным выражением типа bool (до C 23), выражением, контекстуально преобразованным в bool, где преобразование является постоянным выражением (начиная с C 23). Если значение true, то оператор-false отбрасывается (если присутствует), в противном случае оператор-true отбрасывается.
- Что значит «инстанцированный»?
Если инструкция constexpr if появляется внутри шаблонной сущности и если условие не зависит от значения после создания экземпляра, то отброшенный оператор не создается при создании экземпляра заключающего шаблона .
- Что значит «проверено»? Я понимаю, что «проверено» означает, что код был полностью скомпилирован и проверен на любую возможную ошибку в то время.
За пределами шаблона отброшенный оператор полностью проверяется. if constexpr не является заменой директивы #if предварительной обработки:
Комментарии:
1. Отброшено: пропущено, проигнорировано, как будто его там не было.
2. Экземпляр: используется в контексте шаблонов. Означает, что шаблон «воплощен» (фактически определен ) с использованием заданных конкретных аргументов шаблона.
3. @YvesDaoust: Сложнее, чем это, как объяснено в пунктах 2 и 3. «отброшено» действительно вводит в заблуждение ИМО.
4. Проверено: в любом случае это должно быть действительное утверждение. (Даже если его можно отбросить.)
5. Фактически, пункт 1 различает два блока и называет оператор/ветвь, которая не удовлетворяет условию, чтобы впоследствии придать ей некоторые «свойства».
Ответ №1:
Рассмотрим этот пример:
#include <iostream>
#include <string>
template <typename T>
void foo() {
T t;
if constexpr (std::is_same_v<T,std::string>){
std::cout << t.find("asd");
} else {
t = 0;
std::cout << t;
}
}
int main () {
foo<int>(); // (2)
}
Когда T
тип, у которого нет find
метода, std::cout << t.find("asd")
является ошибкой. Тем не менее, шаблон в порядке.
- Что значит «инстанцированный»?
Экземпляр шаблона создан в (2)
. foo
это всего лишь шаблон, создание экземпляра которого приводит к функции foo<int>
, которую вы можете вызвать.
- Что означает «отброшено» в приведенном ниже тексте?
Истинная ветвь отбрасывается при foo<int>
создании экземпляра (потому что условие есть false
). Следовательно, даже если int
у него нет find
метода, код компилируется без ошибок.
Теперь рассмотрим этот аналогичный, но совсем другой пример:
#include <iostream>
int main () {
int x = 0;
if constexpr (true) {
std::cout << x;
} else {
x.find("asd");
}
}
- Что значит «проверено»?
Текст немного надуман, в нем говорится, что в приведенном выше примере false
ветвь отбрасывается, но тем не менее она проверяется, потому что находится вне шаблона. Это просто английский термин: «проверено» означает, что компилятор проверяет правильность кода. int
не имеет метода find
, следовательно, вышеизложенное приводит к ошибке:
<source>:8:15: error: request for member 'find' in 'x', which is of non-class type 'int'
8 | x.find("asd");
| ^~~~
Даже если это утверждение никогда не выполняется, оно должно быть допустимым кодом.
Комментарии:
1. что делать, если изменение
std::cout << t.find("asd");
в вашем первом коде, наwhatever contains errors
?.2. @Roman тогда это то же самое. std::cout < Вы можете заменить его другой ошибкой и все равно
foo<int>()
выполнить компиляцию. Только когда T == std::строка кода в ветви true не отбрасывается и не проверяется