C++17中函数模板中的静态数组初始化(MSVC 2019)
Static array initialization in a function template in C++17 (MSVC 2019)
我正在寻找一种方便高效的方法来初始化函数模板中的静态数组。例如,假设我们有这样一个函数:
template <size_t windowSize>
int process_signal(int currentSignal)
{
// incorrect: inits only 3 elements; want to set all values to -1
static std::array<int, windowSize> window = { -1, -1, -1 };
// do something...
}
通过这种方式,我只能用-1初始化前3个元素,但不能全部初始化。
到目前为止,我提出的最好的解决方案是使用constexpr
函数进行编译时初始化:
template <size_t sz, int value>
constexpr std::array<int, sz> init_array()
{
std::array<int, sz> arr{};
//arr.fill(-1); // will be constexpr since C++20
// operator [] is constexpr in C++17
for (int i = 0; i < sz; ++i)
arr[i] = value;
return arr;
}
template <size_t windowSize>
int process_signal(int currentSignal)
{
// works fine, but extra variable needed
constexpr static std::array<int, windowSize> init_value = init_array<windowSize, -1>();
static std::array<int, windowSize> window = init_value;
// window will be updated...
}
通过这种方式,我可以在编译时初始化数组一次。但是,它需要一个额外的constexpr
变量(在我的例子中是init_value
(来绑定init_array()
函数的结果。如果我在没有它的情况下尝试同样的方法,init_array()
将作为一个正常函数调用(因此初始化不再是编译时(:
template <size_t windowSize>
int process_signal(int currentSignal)
{
// no longer compile-time in MSVC2019
static std::array<int, windowSize> window = init_array<windowSize, -1>();
// window will be updated...
}
是否可以在没有额外constexpr
变量的情况下进行同样的操作?或者,也许它只是针对我的编译器(MSVC 2019(?
不需要额外的变量,只需写:
static auto window = init_array<windowSize, -1>();
初始值设定项仍然是一个常量表达式,编译器应在编译时对其求值。
如果编译器由于某种原因没有正确优化,那么可以使用lambda来存储中间constexpr
变量:
static auto window = []{ constexpr auto x = init_array<windowSize, -1>(); return x; }();
或者你可以把它放在一个单独的函数中,例如init_array
:
template <size_t sz, int value>
constexpr std::array<int, sz> init_array()
{
constexpr auto x = []{
std::array<int, sz> arr{};
//arr.fill(-1); // will be constexpr since C++20
// operator [] is constexpr in C++17
for (int i = 0; i < sz; ++i)
arr[i] = value;
return arr;
}();
return x;
}
您可以使函数更加通用:
template <std::size_t S, typename T>
constexpr auto init_array(const T& value)
{
return std::apply([&](auto... pack){
return std::array{((void)pack, value)...};
}, std::array<int, S>{});
}
用作
static auto window = init_array<windowSize>(-1);
或
template <std::size_t S, auto value>
constexpr auto init_array()
{
constexpr auto x = std::apply([](auto... pack){
return std::array{((void)pack, value)...};
}, std::array<int, S>{});
return x;
}
用作
static auto window = init_array<windowSize, -1>;
强制编译时评估(直到复制(。
相关文章:
- C++17中函数模板中的静态数组初始化(MSVC 2019)
- 如何让MSVC编译器优化多步POD初始化?
- MSVC 2017 在单个翻译单元中违反静态初始化顺序
- C++指向成员的指针的类内初始化会使 MSVC 失败(但 GCC/Clang 工作)
- 为什么静态局部变量的 MSVC 线程安全初始化使用 TLS
- 值初始化:MSVC 与 clang
- 为什么使用 MSVC 编译这个不正确的 std::函数初始化?
- 在MSVC上的数组初始化期间,destructor在不复制或移动构造方的情况下调用
- 为什么 MSVC 和 GCC 不能使用具有默认值的字段初始化结构
- MSVC 19.11 / Visual C 2017:尺寸1和size_t类型的初始化列表误解
- 使用MSVC 2013的类初始化器中的C++11
- 静态 const 数组在 MSVC 中动态初始化
- MSVC和Clang之间的大括号不一致或初始化行为相等
- 当涉及填充时,堆的MSVC初始化
- 我如何让MSVC把未初始化的数据在.bss
- MSVC是否保证在未初始化的本地字符数组中为空字符?
- 本地静态的线程安全初始化:MSVC
- 在MSVC编译器下使用最大成员初始化联合
- 使用双精度的 MSVC 大括号初始化似乎违反了该标准
- 在MSVC和GCC上声明和初始化constexpr的通用语法