Ошибка определения типа шаблона (std::empty как предикат)C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Ошибка определения типа шаблона (std::empty как предикат)

Сообщение Anonymous »

У меня есть вектор векторов, и я хочу проверить, все ли из них пусты. Используя стандартную библиотеку, я попробовал:

Код: Выделить всё

#include 
#include 

int main()
{
std::vector vv;

std::all_of(std::begin(vv), std::end(vv), std::empty);
}
Это приводит к следующей ошибке в clang 7.0:


/usr/bin/../lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/stl_algo.h :508:5:
примечание: шаблон-кандидат игнорируется: не удалось вывести аргумент шаблона
'_Predicate'


Думаю, это стандартное поведение, обусловленное правилами вывода типов. Но в любом случае, какой самый простой способ обойти это?

РЕДАКТИРОВАТЬ: Я принял ответ Rubenvb, потому что он дал простое и разумное объяснение вместе с естественным обходным путем. all_of принимает предикат, который является функцией, объектом функции или лямбда-выражением. std::empty не является ни тем, ни другим, а шаблоном функции. При явном создании экземпляра мы получаем простую функцию, которая должна работать. Удивительно, но большинство компиляторов, которые я пробовал, по-прежнему не компилируются.

Ну, посмотрим:

на GCC 6.3 , он компилируется нормально - https://godbolt.org/g/Pxta7C

но в GCC из магистрали это вызывает внутреннюю ошибку компилятора - https://godbolt.org/g/H6DHt5

Ни Clang from Trunk, ни MSVC 2017 не смогут его скомпилировать:

https://godbolt.org/g/819pbQ (Clang)

https://godbolt.org/g/ua5E8e (MSVC)

EDIT2: Судя по всему, Роберт Анджеюк тоже прав: причина, по которой компилятор не может справиться с этим, заключается в неоднозначном разрешении перегрузки. std::empty имеет 3 разные перегрузки. и два из них одинаково хороши: общий и список std::initializer. Я добился аналогичных результатов со следующей минимальной версией:

Код: Выделить всё

#include 

template
void foo(const T& t);

template
void foo(const std::initializer_list& il);

template
void bar(F f);

int main()
{
bar(foo);
}
Однако есть одно отличие. Этот пример просто не компилируется в GCC из магистрали (вместо вызова ICE).

Подробнее здесь: https://stackoverflow.com/questions/505 ... -predicate
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»