如何将任意 std::integral 类型转换为无符号?

How to cast an arbitrary std::integral type to unsigned?

提问人:StckXchnge-nub12 提问时间:11/7/2023 最后编辑:StckXchnge-nub12 更新时间:11/7/2023 访问量:140

问:

当设置特殊标志时,我试图将 std::integral 类型转换为无符号,即在这种情况下,它应该简单地解释为无符号数字。在这种情况下,这种强制转换是必要的,因为以后需要将数字作为无符号传递给另一个不受我控制的函数。但是,我找不到成功编译的解决方案。

这是一个最有前途的解决方案(我从 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);
}

(使用 g++ --std=c++20 编译)

编译器错误消息:

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

是什么导致了这些问题,您建议如何克服这些问题?

C 无符号 C++ 概念

评论

1赞 463035818_is_not_an_ai 11/7/2023
请在问题中包含编译器错误消息
1赞 463035818_is_not_an_ai 11/7/2023
你只是缺少一个 godbolt.org/z/98T3n8cY7typename
0赞 463035818_is_not_an_ai 11/7/2023
或使用 .通常,您应该更喜欢此类帮助程序类型别名而不是裸成员别名,因为您遇到的正是这个问题std::make_signed_ttype
0赞 463035818_is_not_an_ai 11/7/2023
...你需要要求你的编译器编译为 C++20
0赞 463035818_is_not_an_ai 11/7/2023
您使用的是哪个版本的编译器?

答:

0赞 gera verbun 11/7/2023 #1

根据文档,您应该按照以下示例中的操作:make_unsigned

也就是说,对于您的示例:

using unsigned_num_t = std::make_unsigned_t<decltype(num)>;
const unsigned_num_t unsigned_num = num;

或者正如你被告知的那样,你应该只添加 typename,如下所示:

typename std::make_unsigned<decltype(num)>::type unsigned_num = num;