如何定义C++编译时定义长度的空白数组?
How define array of blanks of C++ compile time defined length?
我想定义一个 ASCII 空白字符串(字符数组),与某些静态常量整数或宏一样长。我希望它发生在编译时,而不是 运行 时间。
例如,如果
static const int numBlanks = 5
然后
char foo[] = " "
(五个空格)
如果
numBlanks = 3
然后
char foo[] = " "
(三个空格)
等等。 (为什么?我想将它与 strstr()
一起使用以定位至少 numBlanks
的序列,并且 numBlanks
可在编译时设置。)
是的,你用new
、memset()
和一个/0
来做,但我想在编译时做一次,而不是在[=49=时一次又一次地做] 时间。
是的,我可以非常接近
char foo[] = " ";
foo[numBlanks] = '[=14=]';
和评论或 assert()
以确保 numBlanks
永远不会大于 foo
的编译长度。
但是我可以在编译时做这一切吗?定义所有空白的字符数组,长度正好为 numBlanks,其中 numBlanks
是 C++ static const int 还是宏?
这是一种使用可变参数模板和 std::make_index_sequence
:
的方法
#include <utility>
template<typename T> struct blank_array;
template<std::size_t... Is>
struct blank_array<std::integer_sequence<std::size_t, Is...>> {
static constexpr char arr[] = {(Is, ' ')..., '[=10=]'};
};
template<std::size_t... Is>
constexpr char blank_array<std::integer_sequence<std::size_t, Is...>>::arr[];
template<std::size_t N>
constexpr const char (&blanks)[N+1] =
blank_array<std::make_index_sequence<N>>::arr;
用法示例:
#include <iostream>
int main()
{
std::cout << "[" << blanks<5> << "]\n";
}
我通过一些实验发现,您可以使用更强大的 constexpr
语句在 c++14 或更高版本中执行此操作。在这种情况下使用递归模板。
#include <cstdio>
#include <array>
template<size_t arrsize, size_t setnum>
constexpr void initVal(std::array<char, arrsize> &tmp) {
std::get<setnum>(tmp) = ' ';
if (setnum) initVal<arrsize, setnum ? setnum - 1 : 0>(tmp);
}
template<size_t arrsize>
constexpr auto initArray() -> std::array<char, arrsize> {
std::array<char, arrsize> tmp{};
std::get<arrsize - 1>(tmp) = '[=10=]';
initVal<arrsize, arrsize - 2>(tmp);
return tmp;
}
constexpr std::array<char, 5 + 1> globalArr = initArray<5 + 1>();
int main()
{
puts(globalArr.data());
}
谢谢大家。我对你的几个回复投了赞成票并标记为答案。
我想我希望的是更简单的东西。这不是世界上最重要的编程要求;我只是想也许我缺少一种直接的方法来做到这一点。你的回答很棒!
我决定最简单的方法是扭转问题:让编码人员指定一个所需长度的字符串并从中导出长度:
// Fill the following blanks array to a length equal to the minimum number of blanks to find (minimum 2)
// 12345678901234567890
static const char blanks[] = " ";
static const int numBlanks = sizeof(blanks)-1;
我想定义一个 ASCII 空白字符串(字符数组),与某些静态常量整数或宏一样长。我希望它发生在编译时,而不是 运行 时间。
例如,如果
static const int numBlanks = 5
然后
char foo[] = " "
(五个空格)
如果
numBlanks = 3
然后
char foo[] = " "
(三个空格)
等等。 (为什么?我想将它与 strstr()
一起使用以定位至少 numBlanks
的序列,并且 numBlanks
可在编译时设置。)
是的,你用new
、memset()
和一个/0
来做,但我想在编译时做一次,而不是在[=49=时一次又一次地做] 时间。
是的,我可以非常接近
char foo[] = " ";
foo[numBlanks] = '[=14=]';
和评论或 assert()
以确保 numBlanks
永远不会大于 foo
的编译长度。
但是我可以在编译时做这一切吗?定义所有空白的字符数组,长度正好为 numBlanks,其中 numBlanks
是 C++ static const int 还是宏?
这是一种使用可变参数模板和 std::make_index_sequence
:
#include <utility>
template<typename T> struct blank_array;
template<std::size_t... Is>
struct blank_array<std::integer_sequence<std::size_t, Is...>> {
static constexpr char arr[] = {(Is, ' ')..., '[=10=]'};
};
template<std::size_t... Is>
constexpr char blank_array<std::integer_sequence<std::size_t, Is...>>::arr[];
template<std::size_t N>
constexpr const char (&blanks)[N+1] =
blank_array<std::make_index_sequence<N>>::arr;
用法示例:
#include <iostream>
int main()
{
std::cout << "[" << blanks<5> << "]\n";
}
我通过一些实验发现,您可以使用更强大的 constexpr
语句在 c++14 或更高版本中执行此操作。在这种情况下使用递归模板。
#include <cstdio>
#include <array>
template<size_t arrsize, size_t setnum>
constexpr void initVal(std::array<char, arrsize> &tmp) {
std::get<setnum>(tmp) = ' ';
if (setnum) initVal<arrsize, setnum ? setnum - 1 : 0>(tmp);
}
template<size_t arrsize>
constexpr auto initArray() -> std::array<char, arrsize> {
std::array<char, arrsize> tmp{};
std::get<arrsize - 1>(tmp) = '[=10=]';
initVal<arrsize, arrsize - 2>(tmp);
return tmp;
}
constexpr std::array<char, 5 + 1> globalArr = initArray<5 + 1>();
int main()
{
puts(globalArr.data());
}
谢谢大家。我对你的几个回复投了赞成票并标记为答案。
我想我希望的是更简单的东西。这不是世界上最重要的编程要求;我只是想也许我缺少一种直接的方法来做到这一点。你的回答很棒!
我决定最简单的方法是扭转问题:让编码人员指定一个所需长度的字符串并从中导出长度:
// Fill the following blanks array to a length equal to the minimum number of blanks to find (minimum 2)
// 12345678901234567890
static const char blanks[] = " ";
static const int numBlanks = sizeof(blanks)-1;