CPP Playground
Curious Case of Concepts (C++ 20) CLANG++(v12) vs G++(v10)
First, you want to write a simple operator<< overload to print your std::vectors
First iteration:
- template <typename T>
- ostream& operator<< (ostream& os, const vector<T>& v) {
- for (auto& e: v) {
- os << e << " ";
- }
- return os;
- }
Now, let us look at a sample main() which uses this
- int main(){
- vector<int> vint(10, 3);
- cout << vint << endl; // works!
- vector<vector<int>> vvint(5, vector<int>(2, 9));
- cout << vvint << endl; // works!
- vector <pair<int,int>> vpair(2);
- cout << vpair << endl; // doesn't; obviously!
- }
What if we want to change our operator overload to be only used if the passed type is indeed that can be printed? E.g., line 9 of the main should have some readable error message in it.
Second Iteration:
- template <typename T>
- concept printable = requires (T t) {
- cout << t;
- };
- template <printable T>
- ostream& operator<< (ostream& os, const vector<T>& v) {
- for (auto& e: v) {
- os << e << " ";
- }
- return os;
- }
with this update to our code, now the failure on main()'s line 9 has a better error message:
g++10:
concept.cpp:27:14: note: constraints not satisfied
clang++12:
concept.cpp:27:14: note: candidate template ignored: constraints not satisfied [with T = std::pair<int, int>] ostream& operator<< (ostream& os, const vector<T>& v) { ^concept.cpp:26:12: note: because 'std::pair<int, int>' does not satisfy 'printable' template <printable T> ^concept.cpp:9:7: note: because 'cout << t' would be invalid: invalid operands to binary expression ('std::ostream' (aka 'basic_ostream<char>') and 'std::pair<int, int>') cout << t;However, this is where it gets interesting!
clang++12 fails for
cout << vvint << endl;
as well; with a similar error.
concept.cpp:27:14: note: candidate template ignored: constraints not satisfied [with T = std::vector<int>] ostream& operator<< (ostream& os, const vector<T>& v) { ^concept.cpp:26:12: note: because 'std::vector<int>' does not satisfy 'printable' template <printable T> ^concept.cpp:9:7: note: because 'cout << t' would be invalid: call to function 'operator<<' that is neither visible in the template definition nor found by argument-dependent lookup cout << t;Need to inspect how g++ and Clang++ actually implement concepts behding the scene - looks like g++ uses a recursive-kinda check for the satisfiability.
to be continued...