C++在编译时将整数转换为字符串
我想做这样的事情:
template<int N>
char* foo() {
// return a compile-time string containing N, equivalent to doing
// ostringstream ostr;
// ostr << N;
// return ostr.str().c_str();
}
看起来 boost MPL 库可能允许这样做,但我真的不知道如何使用它来完成这个任务。这可能吗?
I want to do something like this:
template<int N>
char* foo() {
// return a compile-time string containing N, equivalent to doing
// ostringstream ostr;
// ostr << N;
// return ostr.str().c_str();
}
It seems like the boost MPL library might allow this but I couldn't really figure out how to use it to accomplish this. Is this possible?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
首先,如果通常您在运行时知道该数字,则可以轻松构建相同的字符串。也就是说,如果您的程序中有
12
,则也可以有"12"
。预处理器宏还可以向参数添加引号,因此您可以编写:
这样,每当您编写
STRINGIFICATOR(2)
时,它都会生成“2”。然而,它实际上可以在没有宏的情况下完成(使用编译时元编程)。这并不简单,因此我无法给出确切的代码,但我可以为您提供有关如何执行此操作的想法:
mpl::string
构建附加该字符的编译时字符串。mpl::string
,它具有静态value()
字符串。我花时间将其作为个人练习来实施。最后还不错:
First of all, if usually you know the number at run time, you can as easily build the same string. That is, if you have
12
in your program, you can have also"12"
.Preprocessor macros can add also quotes to arguments, so you can write:
This, whenever you write
STRINGIFICATOR(2)
, it will produce "2".However, it actually can be done without macros (using compile-time metaprogramming). It is not straightforward, so I cannot give the exact code, but I can give you ideas on how to do it:
mpl::string
to build the compile-time string that appends that character.mpl::string
, that has a staticvalue()
string.I took the time to implement it as a personal exercise. Not bad at the end:
我知道这个问题已经有几年了,但我想要一个使用纯 C++11 的解决方案,没有 boost 依赖。所以这里是一些代码(借鉴了这个不同问题的答案的想法):
输出:
I know this question is a few years old now, but I wanted a solution using pure C++11, with no boost dependency. So here is some code (with ideas borrowed from this answer to a different question):
Output:
这可以使用 C++14 来完成,无需任何外部依赖项。该标准的关键补充是能够拥有重要的 constexpr 构造函数,从而允许将功能包含在简单的类中。
给定一个整数模板参数,构造函数可以执行整数到字符串的转换。它存储在成员字符缓冲区中,其大小由附加的 constexpr 函数确定。然后,用户定义的转换提供对缓冲区的访问:
最后,变量模板(另一个 C++14 添加)简化了语法:
功能可以扩展以支持其他基数(例如十六进制)、宽字符类型和通用容器接口;我已将所有内容打包到一个标头中,并将其放在 GitHub 上 tcsullivan/constexpr-to-string 。
使用 C++20,还可以扩展以支持浮点数。浮点文字需要一个容器类型,以前不能作为模板参数。有关实现,请参阅 GitHub 存储库中的
f_to_string.hpp
标头。This can be done using C++14 without any external dependencies. The key addition to the standard is the ability to have non-trivial
constexpr
constructors, allowing the functionality to be contained within a simple class.Given an integer template parameter, the constructor can carry out the integer-to-string conversion. This is stored in a member character buffer whose size is determined by an additional
constexpr
function. Then, a user-defined conversion provides access to the buffer:Finally, a variable template (another C++14 addition) simplifies the syntax:
The functionality can be extended to support other bases (e.g. hexadecimal), wide character types, and the common container interface; I've packed this all into a single header and put it on GitHub at tcsullivan/constexpr-to-string.
With C++20, this can also be extended to support floating-point numbers. A container type is needed for the floating-point literal, which previously could not be a template parameter. See the
f_to_string.hpp
header in the GitHub repo for the implementation.也许我错过了一些东西,但这应该很简单:
不幸的是,这不适用于非类型模板参数。
Maybe i missed something, but this should be as simple as:
Unfortunately this won't work with non-type template parameters.
我见过的一个技巧是在你知道你永远不会有
0..9
范围之外的数字的情况下完成的,如下所示:return '0' + N;< /code>
乍一看,这是令人恼火的限制。然而,令我惊讶的是这种情况出现了多少次。
哦,我知道这会返回一个
char
而不是std::string
。这是一个特点。string
不是一种内置的语言类型,因此无法在编译时创建它。One trick I've seen done in situations where you know for a fact you will never have a number outside the range
0..9
is the following:return '0' + N;
At first blush this is annoyingly limited. However, I'm surprised how many times this condition holds.
Oh, and I'm aware this returns a
char
rather than astd::string
. This is a feature.string
isn't a built in language type, so there's no way to create one at compile time.另一个有用的选项:
Another useful option: