I am trying to cast an std::integral type to unsigned when a special flag is set i.e. it should simply be interpreted as an unsigned number in this case. This cast is necessary in that case, because the number needs to be passed as an unsigned to another function not controlled by me later on. However, I can't find a solution that compiles successfully.
Here's a MWE with the most promising solution (which I took from https://stackoverflow.com/a/33049554):
#include <concepts>
#include <type_traits>
#include <iostream>
bool change = true;
void do_something(const std::floating_point auto num) {
// Do something else
std::cout << "Got floating num: " << num;
return;
}
void do_something(const std::integral auto num) {
if (change) {
// Interpret as unsigned
std::make_unsigned<decltype(num)>::type unsigned_num = num; // FAILS
std::cout << "Got integral and changed to unsigned: " << unsigned_num;
} else {
// Do something else
std::cout << "Got integral and keeping as is: " << num;
return;
}
}
int main() {
do_something(1);
do_something(-1);
do_something(0.5);
change = false;
do_something(1);
do_something(-1);
do_something(0.5);
}
(compile with g++ --std=c++20)
Compiler Error Message:
mwe.cc:7:30: error: ‘floating_point’ in namespace ‘std’ does not name a type; did you mean ‘is_floating_point’?
7 | void do_something(const std::floating_point auto num) {
| ^~~~~~~~~~~~~~
| is_floating_point
mwe.cc:7:45: error: expected ‘,’ or ‘...’ before ‘auto’
7 | void do_something(const std::floating_point auto num) {
| ^~~~
mwe.cc: In function ‘void do_something(int)’:
mwe.cc:9:46: error: ‘num’ was not declared in this scope; did you mean ‘enum’?
9 | std::cout << "Got floating num: " << num;
| ^~~
| enum
mwe.cc: At global scope:
mwe.cc:13:30: error: ‘integral’ in namespace ‘std’ does not name a type; did you mean ‘internal’?
13 | void do_something(const std::integral auto num) {
| ^~~~~~~~
| internal
mwe.cc:13:39: error: expected ‘,’ or ‘...’ before ‘auto’
13 | void do_something(const std::integral auto num) {
| ^~~~
mwe.cc:13:6: error: redefinition of ‘void do_something(int)’
13 | void do_something(const std::integral auto num) {
| ^~~~~~~~~~~~
mwe.cc:7:6: note: ‘void do_something(int)’ previously defined here
7 | void do_something(const std::floating_point auto num) {
| ^~~~~~~~~~~~
mwe.cc: In function ‘void do_something(int)’:
mwe.cc:16:45: error: ‘num’ was not declared in this scope; did you mean ‘enum’?
16 | std::make_unsigned<decltype(num)>::type unsigned_num = num;
| ^~~
| enum
mwe.cc:16:49: error: template argument 1 is invalid
16 | std::make_unsigned<decltype(num)>::type unsigned_num = num;
| ^
mwe.cc:16:57: error: expected initializer before ‘unsigned_num’
16 | std::make_unsigned<decltype(num)>::type unsigned_num = num;
| ^~~~~~~~~~~~
mwe.cc:17:74: error: ‘unsigned_num’ was not declared in this scope; did you mean ‘unsigned’?
17 | std::cout << "Got integral and changed to unsigned: " << unsigned_num;
| ^~~~~~~~~~~~
| unsigned
mwe.cc:20:68: error: ‘num’ was not declared in this scope; did you mean ‘enum’?
20 | std::cout << "Got integral and keeping as is: " << num;
| ^~~
| enum
What is causing these issues and how would you suggest to overcome them?
According to the documentation you should do as in the example here: make_unsigned
That is, for your example:
Or as you were told, you should only add typename, like this: