问题描述
我正在设计实现中,希望从一组特定字符中选择输入作为其字符串文字表示形式。
请考虑以下类集:
class enum BaseType {
BINARY = 2,OCTAL = 8,DECIMAL = 10,HEXADECIMAL = 16
};
template<BaseType BASE = BaseType::DECIMAL> // Default Template
class Foo {
public:
const uint16_t Base{BASE};
private:
std::string digits_;
int64_t integral_value_;
int64_t decimal_value_;
size_t decimal_index_location_;
public:
Foo()
: digits_{""},integral_value_{0},decimal_value_{0}
decimal_index_location_{0}
{}
Foo(const std::string_view digit_sequence)
: digits_{digit_sequence},decimal_value_{0}
decimal_index_location{0}
{
// set values according to the respective digits
// from the decimal point if one exists
// and set the decimal index location if one exists...
}
};
对于其他尚未确定的非默认类型,我可能不得不使用专门化。无论如何,我想将每种情况限制为以下字符集,如下所示:
-
BINARY
:'0'
,'1'
,'.'
-
OCTAL
:['0' - '7']
,'.'
-
DECIMAL
:['0' - '9']
,'.'
-
HEXADECIMAL
:['0' - '9']
,['a' - 'f']
,['A' - 'F']
,'.'
这些对于每种类型都是可接受的输入:
-
BINARY
:-
"010"
,".010"
,"01.0"
,"01.
”等...
-
-
OCTAL
:-
"012345670"
,".012345670"
,"01.2345670"
,"1."
等...
-
-
DECIMAL
:-
"01234567890"
,".01234567890"
,"01.234567890"
,"1."
等...
-
-
HEXADECIMAL
:-
"0123456789abcdef0"
,".0123456789abcdef0"
,"01.23456789abcdef0"
,"1."
等... -
"0123456789ABCDEF0"
,".0123456789ABCDEF0"
,"01.23456789ABCDEF0"
,"1."
等...
-
成为该类的构造函数的string_view
参数的唯一有效输入字符集。
是否有一种简单,优雅且有效的方法?如果是这样,怎么办?究竟是通过抛出异常,编译时还是运行时断言来处理,这并不重要……我只想限制每个模板版本的有效字符集...
编辑
对于每种情况,甚至单个'.'
都是有效输入。例如:
Foo a(".");
将被解释为0
,随后当我合并exponent
部分时,指数将取值为1
,因此结果将是0
而不是{{ 1}}由于电源规则...
解决方法
使用<regex>
,您可以这样做:
static const std::regex binary_regex(R"([01]*\.?[01]*)");
static const std::regex octal_regex(R"([0-7]*\.?[0-7]*)");
static const std::regex decimal_regex(R"([0-9]*\.?[0-9]*)");
static const std::regex hex_regex(R"([0-9a-fA-F]*\.?[0-9a-fA-F]*)");
bool do_match(const std::string& s,const std::regex& regex)
{
// if (s.empty()) { return false; }
std::smatch base_match;
return std::regex_match(s,base_match,regex);
}
您甚至可以通过分组获得点之前和之后的值