Kann ein Konzept gegen std::variant und std::vector geprüft werden?C++

Programme in C++. Entwicklerforum
Guest
 Kann ein Konzept gegen std::variant und std::vector geprüft werden?

Post by Guest »

Hier gibt es einfache (vielleicht naive) Konzepte. Sie sollen Typen abschneiden, die mit einem bestimmten Operator nicht kompatibel sind.

Code: Select all

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
Außerdem gibt es hier synthetische Typen und eine Vorlagenfunktion (eingeschränkt z. B. mit std::less), um diese Konzepte zu testen.

Code: Select all

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 )
{}
Einfache Fälle funktionieren wie erwartet.

Code: Select all

    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
Aber das Hinzufügen von std::variant bringt einige Überraschungen mit sich.

Code: Select all

    foo( non_comparable_variant{} ); // Ok
Und das ist die erste Frage: Es wird kompiliert! Obwohl ich von dem Konzept einen Soft-Error erwartet hatte. Stimmt etwas mit dem Konzept nicht?
Und das Zweite:

Code: Select all

    foo( non_comparable_vector_of_variant{} );
Dieser Aufruf führt bei der Konzeptbewertung zu einem schwerwiegenden Fehler. Der Fehler ist wahrscheinlich außerhalb des unmittelbaren Kontexts aufgetreten. Aber ich kann mir nicht vorstellen, wie ich es loswerden kann.

x86-64 clang 19.1.0 Ausgabe:

Code: Select all

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
Gleiches Verhalten auf modernem GCC, Clang und MSVC.
Live-Beispiel auf Godbolt

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post