Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++, concepts not working with unsigned integers as a result type?

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
like image 578
M.Mac Avatar asked Nov 28 '19 14:11

M.Mac


People also ask

What does unsigned integer do in C?

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);

Why are unsigned integers bad?

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.

How is an unsigned integer stored in C?

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.

Is it good practice for unsigned int?

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).


1 Answers

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.

like image 158
Nicol Bolas Avatar answered Oct 22 '22 10:10

Nicol Bolas