Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ 20 Concepts: Require operator overloading

I am trying to understand how to declare a concept that requires a particular operator is overloaded for a given type. Lets say I have the following function that takes a vector of an arbitrary type and prints it to std::cout:

template<typename printable>
void print_vector(const std::vector<printable>& vec) 
{
  std::cout << '{';
  for (const printable &item : vec) {
    std::cout << item << ',';
  }
  std::cout << '}';
}

This code will work just fine if the type printable has an overloaded << operator, but if it doesn't, then it fails with a very unhelpful compiler error. I feel like I should be able to somehow declare a concept that requires a type has a valid << operator defined, and use that concept in the function declaration, so that I can get a more useful compiler error, but I haven't been able to figure out how to do it.

like image 416
Zach Clayburn Avatar asked Jul 09 '20 20:07

Zach Clayburn


People also ask

What is required for overloading the function operator?

You declare an operator function with the keyword operator preceding the operator. Overloaded operators are distinct from overloaded functions, but like overloaded functions, they are distinguished by the number and types of operands used with the operator. Consider the standard + (plus) operator.

Does C have operator overloading?

C does not support operator overloading at all. You can only implement operations as functions: Colour colour_add(Colour c1, Colour c2); Colour colour_substract(Colour c1, Colour c2); ... You could also switch to C++, but it may be overkill to do it just for the overloading.

What is operator overloading and why is it required in C++?

It allows you to provide an intuitive interface to users of your class, plus makes it possible for templates to work equally well with classes and built-in/intrinsic types. Operator overloading allows C/C++ operators to have user-defined meanings on user-defined types (classes).

Does C++ allow operator overloading?

In C++, we can make operators work for user-defined classes. This means C++ has the ability to provide the operators with a special meaning for a data type, this ability is known as operator overloading.


1 Answers

template <class T>
concept Printable = requires(std::ostream& os, T a)
{
    os << a;
};


template<Printable T>
void print_vector(const std::vector<T>& vec) {
  std::cout << '{';
  for (const auto &item : vec) {
    std::cout << item << ',';
  }
  std::cout << '}';
}

If you wish you could also make it more generic to operate on basic_ostream.


Here is the clang error message:

<source>:30:5: error: no matching function for call to 'print_vector'
    print_vector(x);
    ^~~~~~~~~~~~
<source>:19:6: note: candidate template ignored: constraints not satisfied [with T = X]
void print_vector(std::vector<T> vec) {
     ^
<source>:18:10: note: because 'X' does not satisfy 'Printable'
template<Printable T>
         ^
<source>:10:9: note: because 'os << a' would be invalid: invalid operands to binary expression ('std::ostream' (aka 'basic_ostream<char>') and 'X')
    os << a;
       ^

and gcc:

<source>: In function 'auto test()':
<source>:30:19: error: use of function 'void print_vector(std::vector<T>) [with T = X]' with unsatisfied constraints
   30 |     print_vector(x);
      |                   ^
<source>:19:6: note: declared here
   19 | void print_vector(std::vector<T> vec) {
      |      ^~~~~~~~~~~~
<source>:19:6: note: constraints not satisfied
<source>: In instantiation of 'void print_vector(std::vector<T>) [with T = X]':
<source>:30:19:   required from here  
<source>:8:9:   required for the satisfaction of 'Printable<T>' [with T = X]
<source>:8:21:   in requirements with 'std::ostream& os', 'T a' [with T = X]    
<source>:10:9: note: the required expression '(os << a)' is invalid    
   10 |     os << a;
      |     ~~~^~~~
cc1plus: note: set '-fconcepts-diagnostics-depth=' to at least 2 for more detail
like image 122
bolov Avatar answered Oct 27 '22 00:10

bolov