【问题标题】:Generate constexpr string table, cannot result in a constant expression生成 constexpr 字符串表,不能产生常量表达式
【发布时间】:2019-12-18 13:30:48
【问题描述】:

灵感来自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];
};

【问题讨论】:

  • 您不能将std::string 构造函数用于constexpr 表达式。
  • std::string 不是 constexpr
  • std::string_viewconstexpr,但不确定这有多大帮助。)
  • 顺便说一句,为什么只有那些 1024 而不是所有的 16M?内存空间?
  • 这是一个很好的解释 + 库在 C++11 中执行此操作(减去从 int 的转换):akrzemi1.wordpress.com/2017/06/28/…

标签: c++ constexpr


【解决方案1】:

老实说,我会在 Python 脚本中执行此操作,生成 C++ 源文件(由数组定义组成)作为预构建步骤。

这样,您可以在编译时将信息烘焙到应用程序中,并且信息的来源仍然是易于修改的代码。

constexpr 很好,但有时您只想自动生成一些代码。

【讨论】:

  • 我曾经把这称为生成式编程与泛型编程。 ;-) AWK 是另一个对预处理很有用的工具,它允许源代码由制表符分隔的文本文件(在 Excel 中准备)组成。
【解决方案2】:

问题是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;
}

【讨论】:

  • 是的,但他不必使用 operator+,因为“255;” "NUMBER" ";0" 是一个有效的 C++ 表达式
  • 文字连接和std::string?这是如何结合在一起的?
  • 是的,我的意思是不使用 std::string 作为颜色成员变量。他仍然可以使用我发布的链接中的 StringBuilder。如果他愿意,他将可以访问长度并轻松地从 const char * 构造 std::string
  • 不过,您链接的模板机制可能就足够了。吓人... ;-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-29
  • 2011-01-01
  • 2021-10-04
  • 2011-03-11
  • 2022-01-13
相关资源
最近更新 更多