问题
I am playing around with concepts
and I tried to define a concept
which takes any non-type parameter
and the function isUnsignedInt
checks if the parameter is anunsigned int
, using the required
keyword followed by the concept
.
The problem is, that I can pass a negative integer and there is no error message, that the type is not unsigned int
.
Is my understanding of concepts wrong?
Currently I am working with the gcc 9.2 compiler
and my CMake contains add_compile_options(-fconcepts)
, which enables concepts
.
Code:
template<auto a>
concept special = requires(){
{a} -> unsigned int;
};
template<auto a> requires special<a>
constexpr auto isUnsignedInt(){
return a;
}
int main(){
std::cout << isUnsignedInt<-2>() << std::endl;
return 0;
}
Output:
-2
回答1:
This:
{a} -> unsigned int;
Is no longer a thing in the version of concepts that C++20 will get. By all rights, it should be a compile error. But since that change was made only a few months ago at most, it's not surprising that it compiles under your compiler.
Since it's no longer valid syntax, the real question is what that used to mean. Which also explains why they removed it.
That syntax didn't mean "this expression is the exact type unsigned int
". It meant "this expression is implicitly convertible to the type unsigned int
". Obviously int
is implicitly convertible to unsigned int
, which is why the concept passes for a negative number.
The fact that you expected it to mean "the same" even though it doesn't is precisely why it was removed. So you have to spell it out explicitly: {a} -> std::same_as<unsigned int>
, where std::same_as
is the concept equivalent to the trait std::is_same_v
. Since GCC probably doesn't include the standard library concepts yet, you'll have to write your own equivalent.
来源:https://stackoverflow.com/questions/59090725/c-concepts-not-working-with-unsigned-integers-as-a-result-type