The concept is not checked in the procedure body during the declaration, like a regular non generic type would be. That's unfortunate. I wonder if there's a conservative solution to rule out cases like this without making the concepts unusable?
For those who use C++, C++ 20 concepts fail this test as well ++ #include <iostream> #include <string> #include <cstddef> #include <concepts> template<typename T> concept Aclass = requires(T a) { { a.inum } -> std::convertible_to<int>; }; struct Anobj { Anobj(float fnum, int inum) { this->fnum = fnum; this->inum = inum; } float fnum; int inum; }; struct Bnobj { Bnobj(std::string text, int inum) { this->text = text; this->inum = inum; } std::string text; int inum; }; struct Cnobj { Cnobj(std::string text, int jnum) { this->text = text; this->jnum = jnum; } std::string text; int jnum; }; template<Aclass T> void cdemookay(T a) { std::cout << a.inum << '\n'; } template<Aclass T> void cdemowrong(T a) { std::cout << a.text << '\n'; } /* The compiler rejects this void cdemowrong(Anobj a) { std::cout << a.text << '\n'; } */ int main() { auto p = Anobj(3.33, 7); auto q = Bnobj("empty", 5); auto r = Cnobj("empty", 12); cdemookay(p); cdemookay(q); cdemowrong(q); } Run