c++ - 使用 constexpr 和 std::array 静态初始化获取闰年以替换动态初始化的 std::vector
问题描述
我使用下面的函数来创建一系列年份之间的闰年列表:
// dynamic initialization
std::vector<int> create_leap_years(const int start_year, const int end_year)
{
std::vector<int> collection;
for (auto year = start_year; year < end_year; year++)
{
const auto is_leap_year = (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
if (is_leap_year)
{
collection.emplace_back(year);
}
}
return collection;
}
我尝试学习 constexpr 并使用它来创建指定年份范围内闰年列表的静态初始化。我应该创建一个向量然后将其转换为 std::array 吗?如果我尝试一个函数来返回一个固定数组,如下所示:
// static initialization
static constexpr std::array<int,24>& create_leap_years(const int start_year, const int end_year)
{
// Error: variable in constexpr function does not have automatic storage duration
static const std::array<int, 24> collection =
{ 1904, 1908, 1912, 1916, 1920, 1924, 1928, 1932, 1936,
1940, 1944, 1948, 1952, 1956, 1960, 1964, 1968,
1972, 1976, 1980, 1984, 1988, 1992, 1996 };
return collection;
}
Visual Studio 2019 返回以下错误,我不确定从那里去哪里:
错误:constexpr 函数中的变量没有自动存储持续时间
下面是我尝试完成的完整示例:
#include <iostream>
#include <vector>
#include <array>
#if 1
// dynamic initialization
std::vector<int> create_leap_years(const int start_year, const int end_year)
{
std::vector<int> collection;
for (auto year = start_year; year < end_year; year++)
{
const auto is_leap_year = (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
if (is_leap_year)
{
collection.emplace_back(year);
}
}
return collection;
}
#else
// static initialization
static constexpr std::array<int,24>& create_leap_years(const int start_year, const int end_year)
{
// Error: variable in constexpr function does not have automatic storage duration
static const std::array<int, 24> collection =
{ 1904, 1908, 1912, 1916, 1920, 1924, 1928, 1932, 1936,
1940, 1944, 1948, 1952, 1956, 1960, 1964, 1968,
1972, 1976, 1980, 1984, 1988, 1992, 1996 };
return collection;
}
#endif
int main()
{
const auto collection = create_leap_years(1900, 2000);
for (auto year : collection) std::cout << year << " ";
std::cout << std::endl;
return 0;
}
在函数的更新下方,根据我得到的数组按值返回的反馈返回数组:
std::array<int, 100> create_leap_years(const int start_year, const int end_year)
{
static std::array<int, 100> collection{};
auto idx = 0;
for (auto year = start_year; idx < 100 && year < end_year; year++)
{
const auto is_leap_year = (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
if (is_leap_year)
{
collection[idx++] = year;
}
}
return collection;
}
解决方案
constexpr 函数中不能有静态变量。未来可能会放宽这一规则。
使变量 constexpr 而不是静态的。按值返回。
constexpr std::array<int,24> get_1900s_leap_years()
{
constexpr std::array<int, 24> collection =
{ 1904, 1908, 1912, 1916, 1920, 1924, 1928, 1932, 1936,
1940, 1944, 1948, 1952, 1956, 1960, 1964, 1968,
1972, 1976, 1980, 1984, 1988, 1992, 1996 };
return collection;
}