I asked a very similar question in template method in a C++ 20 'concepts', and the reason I am asking again is because an AI service said it is part of the C++ standard, although gcc (11.4.0) and clang (14.0.0) do not compile.
This is the code I want to compile, almost identical to the one AI service generated:
#include <concepts>
template <typename T>
concept C = requires(T a) {
{ a.m1(std::declval<int>()) } -> std::convertible_to<int>;
template <std::unsigned_integral U> {
a.m2(std::declval<int>())
} -> std::convertible_to<int>;
};
template <C t> void f(t &p_t) { p_t.m1(3); }
class S {
public:
int m1(int i) { return 2 * i; }
template <std::unsigned_integral t> int m2(t p_t) { return p_t; }
};
int main() {
S _s;
f(_s);
}
The code fails to compile in line template <std::unsigned_integral U>
with the report: Expected expression
.
So, are template methods in concepts supported in C++20, but not yet implemented; or is my code wrong; or the AI service generated a incorrect code?
You cannot have a template in a requires clause. But your concept can have a second template argument:
template<typename T, typename U>
concept C = requires(T a, U in)
{
{ a.m1(int{}) } -> std::convertible_to<int>;
std::unsigned_integral<U>; // force U to be unsigned_integral here
{ a.template m2<U>(U{}) } -> std::convertible_to<int>;
};
Because concepts do not allow for sondtrainment see here, you need to explicitly check that U
is a std::unsigned_integral
as well.
Now C
has two template arguments, thus your function f
needs to be templates over two params as well:
template<std::unsigned_integral U, C<U> t>
void f(t& p_t) { p_t.m1(3); } // call with f<unsigned>(_s);
but as you know what kind of unsigned type you have when you call f, this should not be a problem. If you do not need m2
in the function you can decide to provide a default type for U
e.g. std::unsigned_integral U = unsigned
. But then it might be sensible to take apart your concept, if it is not needed in combination anyways.