問題描述
能夠在 C++ 編譯時創建和操作字符串有幾個有用的應用.盡管可以在 C++ 中創建編譯時字符串,但該過程非常繁瑣,因為該字符串需要聲明為可變字符序列,例如
Being able to create and manipulate strings during compile-time in C++ has several useful applications. Although it is possible to create compile-time strings in C++, the process is very cumbersome, as the string needs to be declared as a variadic sequence of characters, e.g.
using str = sequence<'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!'>;
字符串連接、子字符串提取等操作可以輕松實現為對字符序列的操作.是否可以更方便地聲明編譯時字符串?如果沒有,是否有工作中的提案可以方便地聲明編譯時字符串?
Operations such as string concatenation, substring extraction, and many others, can easily be implemented as operations on sequences of characters. Is it possible to declare compile-time strings more conveniently? If not, is there a proposal in the works that would allow for convenient declaration of compile-time strings?
理想情況下,我們希望能夠如下聲明編譯時字符串:
Ideally, we would like to be able to declare compile-time strings as follows:
// Approach 1
using str1 = sequence<"Hello, world!">;
或者,使用用戶定義的文字,
or, using user-defined literals,
// Approach 2
constexpr auto str2 = "Hello, world!"_s;
其中 decltype(str2)
將有一個 constexpr
構造函數.可以實現方法 1 的更混亂版本,利用您可以執行以下操作的事實:
where decltype(str2)
would have a constexpr
constructor. A messier version of approach 1 is possible to implement, taking advantage of the fact that you can do the following:
template <unsigned Size, const char Array[Size]>
struct foo;
然而,數組需要有外部鏈接,所以要使方法 1 起作用,我們必須這樣寫:
However, the array would need to have external linkage, so to get approach 1 to work, we would have to write something like this:
/* Implementation of array to sequence goes here. */
constexpr const char str[] = "Hello, world!";
int main()
{
using s = string<13, str>;
return 0;
}
不用說,這很不方便.方法2實際上是不可能實現的.如果我們要聲明一個 (constexpr
) 文字運算符,那么我們將如何指定返回類型?由于我們需要操作符返回一個可變字符序列,所以我們需要使用 const char*
參數來指定返回類型:
Needless to say, this is very inconvenient. Approach 2 is actually not possible to implement. If we were to declare a (constexpr
) literal operator, then how would we specify the return type? Since we need the operator to return a variadic sequence of characters, so we would need to use the const char*
parameter to specify the return type:
constexpr auto
operator"" _s(const char* s, size_t n) -> /* Some metafunction using `s` */
這會導致編譯錯誤,因為 s
不是 constexpr
.嘗試通過執行以下操作來解決此問題并沒有多大幫助.
This results in a compile error, because s
is not a constexpr
. Trying to work around this by doing the following does not help much.
template <char... Ts>
constexpr sequence<Ts...> operator"" _s() { return {}; }
標準規定這種特定的文字運算符形式保留用于整數和浮點類型.雖然 123_s
會起作用,但 abc_s
不會.如果我們完全放棄用戶定義的文字,而只使用常規的 constexpr
函數會怎樣?
The standard dictates that this specific literal operator form is reserved for integer and floating-point types. While 123_s
would work, abc_s
would not. What if we ditch user-defined literals altogether, and just use a regular constexpr
function?
template <unsigned Size>
constexpr auto
string(const char (&array)[Size]) -> /* Some metafunction using `array` */
和以前一樣,我們遇到的問題是,數組現在是 constexpr
函數的參數,它本身不再是 constexpr
類型.
As before, we run into the problem that the array, now a parameter to the constexpr
function, is itself no longer a constexpr
type.
我相信應該可以定義一個 C 預處理器宏,它將字符串和字符串的大小作為參數,并返回由字符串中的字符組成的序列(使用 BOOST_PP_FOR
,字符串化、數組下標等).但是,我沒有時間(或足夠的興趣)來實現這樣的宏 =)
I believe it should be possible to define a C preprocessor macro that takes a string and the size of the string as arguments, and returns a sequence consisting of the characters in the string (using BOOST_PP_FOR
, stringification, array subscripts, and the like). However, I do not have the time (or enough interest) to implement such a macro =)
推薦答案
我沒有看到任何東西可以與 Scott Schurr 的 str_const
在 C++ Now 2012 上發表.不過它確實需要 constexpr
.
I haven't seen anything to match the elegance of Scott Schurr's str_const
presented at C++ Now 2012. It does require constexpr
though.
以下是您如何使用它,以及它可以做什么:
Here's how you can use it, and what it can do:
int
main()
{
constexpr str_const my_string = "Hello, world!";
static_assert(my_string.size() == 13, "");
static_assert(my_string[4] == 'o', "");
constexpr str_const my_other_string = my_string;
static_assert(my_string == my_other_string, "");
constexpr str_const world(my_string, 7, 5);
static_assert(world == "world", "");
// constexpr char x = world[5]; // Does not compile because index is out of range!
}
沒有比編譯時范圍檢查更酷的了!
It doesn't get much cooler than compile-time range checking!
無論是使用還是實現,都沒有宏.并且對字符串大小沒有人為限制.我會在這里發布實現,但我尊重 Scott 的隱含版權.實現在他的演示文稿的一張幻燈片上,鏈接到上面.
Both the use, and the implementation, is free of macros. And there is no artificial limit on string size. I'd post the implementation here, but I'm respecting Scott's implicit copyright. The implementation is on a single slide of his presentation linked to above.
這篇關于在 C++ 中方便地聲明編譯時字符串的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!