首页 > 解决方案 > 生成 constexpr 字符串表,不能产生常量表达式

问题描述

灵感来自https://stackoverflow.com/a/37413361/1734357我希望制作一个固定且已知大小的字符串颜色查找表,因此我不需要对其进行模板化,但字符串不是 constexpr

怎么办?

struct Colors
{
    constexpr Colors() : colors()
    {
        for (size_t i = 0; i < 256; i++)
            colors[i] = "0;" + to_string(i) + ";255";
        for (size_t i = 0; i < 256; i++)
            colors[256 + i] = "0;255;" + to_string(255 - i);
        for (size_t i = 0; i < 256; i++)
            colors[2 * 256 + i] = to_string(i) + ";255;0";
        for (size_t i = 0; i < 256; i++)
            colors[3 * 256 + i] = "255;" + to_string(255 - i) + ";0";
    }
    string colors[4*256];
};

标签: c++constexpr

解决方案


问题是 to_string 返回 std::string,而 std::string 不是 constexpr 可构造的。

这个问题可以通过使用Sprout constexpr library来解决。尽管您可能会对编译时间感到失望。

#include <iostream>
#include <sprout/string.hpp>
#include <sprout/array.hpp>
#include <sprout/algorithm/transform.hpp>
#include <sprout/numeric/iota.hpp>

struct colorConv {
  typedef sprout::string<20> result_type;

  constexpr result_type
  operator()(int n) const {
      return n / 256 == 0 ? "0;" + sprout::to_string(255 - n) + ";255"
      : n / 256 == 1 ? "0;255;" + sprout::to_string(2 * 255 + 1 - n)
      : n / 256 == 2 ? sprout::to_string(3 * 255 + 2 - n ) + ";255;0;"
      : "255;" + sprout::to_string(4 * 255 + 3 - n) + ";0";
  }
};

struct Colors {
private:
  typedef colorConv::result_type string;
  constexpr static auto source = sprout::iota<sprout::array<int, 256*4> >(0);

public:
  constexpr static auto colors = sprout::transform<sprout::array<string, 256*4> >(
      sprout::begin(source),
      sprout::end(source),
      colorConv()
  );
};

int main() {
  auto& a = Colors::colors;

  for (auto&& str : Colors::colors) {
    std::cout << str << std::endl;
  }

  return 0;
}

推荐阅读