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
An unsigned Integer means the variable can hold only a positive value. This format specifier is used within the printf() function for printing the unsigned integer variables. printf(“%u”, value);
The big problem with unsigned int is that if you subtract 1 from an unsigned int 0, the result isn't a negative number, the result isn't less than the number you started with, but the result is the largest possible unsigned int value. And this is what makes unsigned int error prone.
In the case of an unsigned integer, only positive numbers can be stored. In this data type, all of the bits in the integer are used to store a positive value, rather than having some reserved for sign information.
The Google C++ style guide recommends avoiding unsigned integers except in situations that definitely require it (for example: file formats often store sizes in uint32_t or uint64_t -- no point in wasting a signedness bit that will never be used).
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With