gpt4 book ai didi

c++ - 如何为非类型模板参数使用数字分隔符?

转载 作者:可可西里 更新时间:2023-11-01 18:20:14 27 4
gpt4 key购买 nike

我有一个模板,它采用 unsigned long long 类型的非类型模板参数。实例化此模板很快就会变得困惑,因为它涉及太多数字。事实上,理想情况下,我会使用二进制表示,使情况更糟:最多有 64 个 01 字符。我怎样才能创建一个视觉上可识别的论点。例如:

template <unsigned long long>
struct use_mask {
// for this question it doesn't matter what the template actually does
};

int main() {
use_mask<0b1001001010010010> unreadable; // OK, there are no binary literals
use_mask<0b1001,0010,1001,0010> more_readable; // ... nor are there digit separators
}

有没有办法近似后一种表示法,可能在值前后有一些东西?

最佳答案

以下是我对自己问题的回答:使用作为 constexpr 实现的用户定义文字和字符串文字可以有效地为相关值指定解析器!有两部分略显丑陋:

  1. 实际文字用双引号括起来。
  2. 在所述字符串的末尾有一个用户定义的文字。

除此之外,这种方法实际上允许指定整数文字,包括数字分隔符。我目前还不能创建一个精美的版本来验证分隔符是否位于正确的位置,但这应该只是正确编程的一个小细节。下面是一个实现相应用户定义文字的程序,它允许像这样使用

use_mask<"0b0101,0101,0101,0101,0011,0101"_sep> um1;
use_mask<"0x0123,4567,89ab,cdef"_sep> um2;

当然,这实际上也是在使用文字。实际文字是

"0b0101,0101,0101,0101,0011,0101"_sep
"0x0123,4567,89ab,cdef"_sep

...而且它们可以完全分开使用。抛出异常的错误消息不一定像我希望的那样漂亮。还指出,使用用户定义的文字来处理数字分隔符会排除使用其他用户定义的文字。

#include <algorithm>
#include <iostream>
#include <stdexcept>

template <unsigned long long Value>
struct use_mask {
static constexpr unsigned long long value = Value;
};

// ------------------------------------------------------------------------

constexpr bool is_digit(char c, unsigned base)
{
return '0' <= c && c < '0' + int(base < 10u? base: 10u);
}

constexpr bool is_hexdigit(char c)
{
return ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F');
}

constexpr unsigned long long hex_value(char c)
{
return c - (('a' <= c && c <= 'f')? 'a': 'A') + 10;
}

// ------------------------------------------------------------------------

constexpr unsigned long long decode(unsigned long long value,
unsigned base,
char const* str, size_t n)
{
return n == 0
? value
: (str[0] == ','
? decode(value, base, str + 1, n - 1)
: (is_digit(str[0], base)
? decode(value * base + str[0] - '0', base, str + 1, n - 1)
: (base == 16u && is_hexdigit(str[0])
? decode(value * base + hex_value(str[0]),
base, str + 1, n - 1)
: throw "ill-formed constant with digit separators"
)
)
);
}

constexpr unsigned long long operator"" _sep(char const* value,
std::size_t n)
{
return 2 < n && value[0] == '0'
? ((value[1] == 'b' || value[1] == 'B')
? decode(0ull, 2, value + 2, n - 2)
: ((value[1] == 'x' || value[1] == 'X')
? decode(0ull, 16, value + 2, n - 2)
: decode(0ull, 8, value + 1, n - 1)))
: decode(0ull, 10, value, n);
}

int main()
{
std::cout << use_mask<"0b1010,1010"_sep>::value << "\n";
std::cout << use_mask<"02,52"_sep>::value << "\n";
std::cout << use_mask<"1,70"_sep>::value << "\n";
std::cout << use_mask<"0xA,A"_sep>::value << "\n";
#ifdef ERROR
std::cout << use_mask<"0xx,A"_sep>::value << "\n";
#endif

std::cout << use_mask<"0b0101,0101,0101,0101,0011,0101"_sep>::value
<< '\n';
std::cout << use_mask<"0x0123,4567,89ab,cdef"_sep>::value << '\n';
}

关于c++ - 如何为非类型模板参数使用数字分隔符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18951658/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com