Насколько я понимаю, поиск зависимого имени не происходит до создания экземпляра шаблона, а вызовы шаблона в отброшенном операторе if-constexpr не создаются. Таким образом, я ожидаю, что шаблон или общая лямбда, которая имеет неправильный формат из-за отсутствия зависимых имен, не будет вызывать ошибок компиляции, пока она используется только в отброшенных операторах if-constexpr. Похоже, что в некоторых случаях это так и есть. Например, возьмем:
struct Struct {};
Struct s;
template
void foo(T& s) {
s.non_existing_member = 0;
}
struct A {
template
void operator()(T& s) { // note 'void' return type
s.non_existing_member = 0;
}
};
struct B {
template
auto operator()(T& s) { // note 'auto' return type
s.non_existing_member = 0;
}
};
Как и ожидалось, ошибки компиляции не возникают:
if constexpr (false) {
foo(s);
A{}(s);
}
[](auto& s) {
if constexpr (false) {
s.non_existing_member = 0;
}
}(s);
Однако они жалуются на пропавшего участника:
if constexpr (false) {
auto bar = [](auto& s) {
s.non_existing_member = 0;
};
// error: no member named 'non_existing_member' in 'Struct'
bar(s); // note: in instantiation of function template specialization 'main()::(anonymous class)::operator()'
B{}(s); // note: in instantiation of function template specialization 'B::operator()' requested here
}
Я не совсем понимаю, чем отличаются два приведенных выше случая. Я получаю аналогичные ошибки, ссылающиеся на имена зависимых типов, например. typename T::Type.
Перечитываю документацию (спасибо @Jarod42):
Вне шаблона отброшенный оператор полностью проверяется. if constexpr не является заменой директивы предварительной обработки #if.
Если оператор constexpr if появляется внутри шаблонной сущности, и если после создания экземпляра условие не зависит от значения, экземпляр отброшенного оператора не создается при создании экземпляра включающего шаблона.
На самом деле я бы ожидал, что foo(s ); и A{}(s); также для сбоя компиляции. Однако они этого не делают ни с последними версиями clang, gcc, ни MSVC. Я также ожидаю, что следующее будет работать, и это так. Полный пример.
template
void baz(T& s) {
if constexpr (false) {
s.non_existing_member = 0;
}
}
struct C {
template
auto operator()(T& s) {
if constexpr (false) {
s.non_existing_member = 0;
}
}
};
int main() {
baz(s);
C{}(s);
}
Похоже, что указание типа возвращаемого значения общей лямбды работает (разрешает компиляцию) с gcc и MSVC, но не с clang:
auto bar = [](auto& s) -> void {
s.non_existing_member = 0;
};
Подробнее здесь: https://stackoverflow.com/questions/784 ... on-templat
Ошибка зависимого имени при отброшенном экземпляре if-constexpr шаблона функции или универсальной лямбды ⇐ C++
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение