首页 > 解决方案 > 使用 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;
}

标签: c++c++17

解决方案


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;
}

推荐阅读