#include #include /* requires -std=c++20 */ /* C++20 standardized "concepts" which are compile-time evaluated requirements for template instantiations. The concept is itself usually defined under a template. The syntax and documentation available are both still very confusing, but it is without a doubt something useful. It is capable of defining *semantic* requirements instead of only syntactic requirements for types and values that can instantiate templates. Other languages can specify that the types satisfy certain signatures (interfaces or traits) but concepts are unique to modern C++. However, it still remains that the concept requirements are not checked until instantiated. You can still write garbage code inside a template class and not have it type-checked until the template is both instantiated and the offending method is called (see the h() method in generic_struct below). */ template concept MyRestrictions = N>0 && T::x != T::y && requires(T v) { {v.g(1)} -> std::same_as; // specifies that v.g(int)->int exists }; // concept MyRestrictions template requires MyRestrictions struct generic_struct { T A[N]; // array of N T-objects, N>0 verified when template instantiated. void f() { int sum=0; for (auto& s:A) { sum += s.g(2); } std::cout << sum << std::endl; } // But the following still compiles until the instantiated methods are called T h() { return "abc"; } double dontcallme() { return "abc" / A[0]; } }; //generic_struct struct mystruct { static const int x{1}; static const int y{2}; // x,y must be static else they're instance values, not class values, // they must also be const (or constexpr) else their values are not // known at compile time. int z{0}; int g(int d) { return d*(x+y+z); } bool operator <(mystruct& b) { return true; } //overloads < operator: }; struct yourstruct { static const int x{1}; static const int y{1}; double z; int g(int d) { return d/(x+y+(int)z);} }; // Another example: template requires std::totally_ordered && std::is_swappable_v void swapsort(T A[], int len) { for(int i=0;i mine; mine.f(); //mine.h(); //only with this will there be a compiler error for h function generic_struct yours; //compiler error int I[4] = {4,1,2,3}; swapsort(I,4); //OK mystruct A[2] = {mystruct(),mystruct()}; //swapsort(A,2); //Not OK because of concept requirement (even with '<') return 0; }//main /* compiler error: concepts.cpp:6:38: note: the expression ‘(T::x) != (T::y) [with T = yourstruct]’ evaluated to ‘false’ 6 | concept MyRestrictions = N>0 && T::x != T::y && requires(T v) { | ~~^~~~~~~ */ // see https://en.cppreference.com/w/cpp/concepts for a list of built-in // std concepts.