Можно ли проверить концепцию на соответствие std::variant и std::vector?C++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 Можно ли проверить концепцию на соответствие std::variant и std::vector?

Сообщение Anonymous »

Здесь есть простые (возможно, наивные) концепции. Они предназначены для отсечения типов, несовместимых с данным оператором.

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

namespace concepts
{
template
concept operator_compatible_with = requires ( T const& l, U const& r )
{
{ Op{}( l, r ) };
};

template
concept operator_compatible = operator_compatible_with;
} // namespace concepts
Кроме того, здесь представлены синтетические типы и функция шаблона (ограниченная, например, с помощью std::less) для проверки этих концепций.

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

class non_comparable
{
public:
auto operator(non_comparable const& other) const = delete;
};
using non_comparable_variant           = std::variant;
using non_comparable_vector            = std::vector;
using non_comparable_vector_of_variant = std::vector;

template
void foo( T&& test )
{}
Простые случаи работают так, как ожидалось.

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

    foo( 5 ); // Ok
foo( std::vector{} ); // Ok
foo( std::vector{} ); // Ok

//foo( non_comparable{} ); // Error: constraints not satisfied
//foo( non_comparable_vector{} ); // Error: constraints not satisfied
Но добавление std::variant преподносит некоторые сюрпризы.

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

    foo( non_comparable_variant{} ); // Ok
И это первый вопрос: Он компилируется! Хотя я ожидал от концепции софтовой ошибки. Что-то не так с концепцией?
И второе:

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

    foo( non_comparable_vector_of_variant{} );
Этот вызов выдает серьезную ошибку во время оценки концепции. Вероятно, ошибка произошла вне непосредственного контекста. Но я не представляю, как от этого избавиться.

Вывод x86-64 clang 19.1.0:

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

In file included from :1:
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:1264:39: error: overload resolution selected deleted operator ''
1264 |   _VARIANT_RELATION_FUNCTION_TEMPLATE( decltype(std::forward(__t) < std::forward(__u))
|                                            ^
:10:11: note: while substituting deduced template arguments into function template 'operator()' [with _Tp = const std::vector &, _Up = const std::vector &]
10 |         { Op{}( l, r ) };
|           ^
:10:11: note: in instantiation of requirement here
10 |         { Op{}( l, r ) };
|           ^~~~~~~~~~~~
:8:40: note: while substituting template arguments into constraint expression here
8 |     concept operator_compatible_with = requires ( T const& l, U const& r )
|                                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9 |     {
|     ~
10 |         { Op{}( l, r ) };
|         ~~~~~~~~~~~~~~~~~
11 |     };
|     ~
:14:35: note: while checking the satisfaction of concept 'operator_compatible_with' requested here
14 |     concept operator_compatible = operator_compatible_with;
|                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:14:35: note: while substituting template arguments into constraint expression here
14 |     concept operator_compatible = operator_compatible_with;
|                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:27:10: note: while checking the satisfaction of concept 'operator_compatible' requested here
27 | template
|          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:27:10: note: while substituting template arguments into constraint expression here
27 | template
|          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:46:5: note: while checking constraint satisfaction for template 'foo' required here
46 |     foo( non_comparable_vector_of_variant{} );
|     ^~~
:46:5: note: in instantiation of function template specialization 'foo' requested here
:20:10: note: candidate function has been explicitly deleted
20 |     auto operator(non_comparable const& other) const = delete;
|          ^
:20:10: note: candidate function (with reversed parameter order) has been explicitly deleted
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:1264:3: note: candidate template ignored: could not match 'const variant' against 'const variant_alternative_t' (aka 'const non_comparable')
1264 |   _VARIANT_RELATION_FUNCTION_TEMPLATE( decltype(std::forward(__t) < std::forward(__u))
|                                            ^
:10:11: note: while substituting deduced template arguments into function template 'operator()' [with _Tp = const std::vector &, _Up = const std::vector &]
10 |         { Op{}( l, r ) };
|           ^
:10:11: note: in instantiation of requirement here
10 |         { Op{}( l, r ) };
|           ^~~~~~~~~~~~
:8:40: note: while substituting template arguments into constraint expression here
8 |     concept operator_compatible_with = requires ( T const& l, U const& r )
|                                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9 |     {
|     ~
10 |         { Op{}( l, r ) };
|         ~~~~~~~~~~~~~~~~~
11 |     };
|     ~
:14:35: note: while checking the satisfaction of concept 'operator_compatible_with' requested here
14 |     concept operator_compatible = operator_compatible_with;
|                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:14:35: note: while substituting template arguments into constraint expression here
14 |     concept operator_compatible = operator_compatible_with;
|                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:27:10: note: while checking the satisfaction of concept 'operator_compatible' requested here
27 | template
|          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:27:10: note: while substituting template arguments into constraint expression here
27 | template
|          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:46:5: note: while checking constraint satisfaction for template 'foo' required here
46 |     foo( non_comparable_vector_of_variant{} );
|     ^~~
:46:5: note: in instantiation of function template specialization 'foo' requested here
/opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/bits/invoke.h:90:5: note: candidate template ignored: substitution failure [with _Callable = (lambda at /opt/compiler-explorer/gcc-14.2.0/lib/gcc/x86_64-linux-gnu/14.2.0/../../../../include/c++/14.2.0/variant:1264:3), _Args = ]: no type named 'type' in 'std::__invoke_result'
89 |     constexpr typename __invoke_result::type
|                                                              ~~~~
90 |     __invoke(_Callable&& __fn, _Args&&...  __args)
|     ^
2 errors generated.
Compiler returned: 1
То же самое поведение в современных gcc, clang и msvc.
Живой пример на godbolt

Подробнее здесь: https://stackoverflow.com/questions/793 ... stdvariant
Реклама
Ответить Пред. темаСлед. тема

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

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

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

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

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

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