Ошибка в концепциях C++20 с функциями-членами шаблона и std::invocable

Я экспериментировал с концепциями C ++ 20 и библиотекой Eigen и обнаружил неожиданное поведение. В частности, рассмотрите следующую концепцию, требующую, чтобы тип мог быть вызван с помощью Eigen::Matrix<double, -1, 1>> объект или Eigen::Matrix<char, -1, 1>> один:

      template <class FOO_CONCEPT>
concept FooConcept = std::invocable<FOO_CONCEPT, Eigen::Matrix<double, -1, 1>> &&
    std::invocable<FOO_CONCEPT, Eigen::Matrix<char, -1, 1>>;

Затем посмотрите на закомментированную строку (*) в следующей структуре:

      struct Foo {
    // template <typename T>    <----    (*)
    void operator()(Eigen::Matrix<double, -1, 1>) {
    }

    void operator()(Eigen::Matrix<float, -1, 1>) {
    }
};

Обратите внимание, что класс Foo не удовлетворяет требованиям FooConceptпоскольку его нельзя вызвать с аргументом. Действительно:

      std::cout << FooConcept<Foo> << std::endl;

отпечатки 0. Однако, когда я переключаю строчный комментарий (*), т. Е. Когда operator()это шаблон, как ни странно печатается тот же код. Это ошибка? Я получил эти результаты, используя Clang 12.0.1 и GCC 11.1.0 для компиляции кода в Visual Studio Code. Спасибо за любую помощь, которую вы можете оказать!

PS: линия

       std::cout << std::is_convertible<Eigen::Matrix<char, -1, 1>, Eigen::Matrix<float, -1, 1>>()
              << std::endl;

отпечатки 1, но Eigen::Matrix<char, -1, 1> объект не может быть неявно преобразован в Eigen::Matrix<float, -1, 1>. Это очередная ошибка? И связано ли это как-то с вышеупомянутой проблемой?

1 ответ

Конвертируемый просто определяет, существует ли перегрузка. В случае Эйгена преобразование перегрузки между этими типами существует, но тело имеет static_assert.

is_convertableникак не инстанцирует тело конверсионной операции , прежде чем сказать это работает. Это сделано намеренно, чтобы разрешение перегрузки C ++ не требовало компиляции огромного количества кода.

Чтобы ваши черты работали, Eigen необходимо переписать, чтобы он поддерживал методы и операторы преобразования, удобные для "SFINAE".

Сбой в вашем тесте был вызван тем, что матрица символов преобразована в оба, что неоднозначно, поэтому признак не работает. Вы не поэтому думали, что это не удалось.

Добавление template<class T> означает, что перегрузка thst не учитывается (невозможно вывести значение T), поэтому однозначно выбрано преобразование в массив с плавающей запятой.

Другие вопросы по тегам