C++20是朝着使得在编译时使用std::string
变得可能的一步,但P0980并不允许您编写像您问题中的代码那样的代码:
C++20是为了实现在编译时使用
std::string
而迈出的一步,但是P0980不允许你编写像你提问中那样的代码。
constexpr std::string constString = "constString"
之所以会这样,是因为constexpr
std::string
仅允许在constexpr
函数(常量表达式计算上下文)中使用。由constexpr
std::string
分配的内存必须在函数返回之前被释放——这就是所谓的短暂分配,并且这些内存不能泄露到运行时中对于constexpr
对象(存储在数据段中)的“泄漏”。例如,在当前 VS2022 预览版(cl 版本:19.30.30704)中编译上面那行代码会导致以下错误:
1> : error C2131: expression did not evaluate to a constant
1> : message : (sub-)object points to memory which was heap allocated during constant evaluation
这是因为它试图进行一次非瞬时分配,而这是不允许的 - 这意味着要将内存分配到已编译二进制文件的数据段中。
在 p0784r1 中的“非瞬时(Non-transient)分配”一节中,您可以发现有一个计划允许将瞬时内存转换为静态内存(重点在于“我”):
那么对于在评估完成时尚未被解除分配的存储怎么办?我们可以禁止这样做,但确实存在非常强烈的使用情况。例如,这可能是更灵活的“字符串字面量”类的基础。因此,我们建议,如果非瞬时 constexpr 分配有效(将在下面描述),则分配的对象将提升为静态存储期。
有一种方法可以导出瞬时的 std::string
数据以便在运行时使用它。您必须将其复制到 std::array
中,问题是计算最终的 std::array
大小,您可以预设一些大的大小或两次计算 std::string
- 一次获取大小,一次获取实际数据。以下代码成功地在当前的 VS2022 预览版 5 上编译并运行。它基本上是使用分隔符连接三个单词:
constexpr auto join_length(const std::vector<std::string>& vec, char delimiter) {
std::size_t length = std::accumulate(vec.begin(), vec.end(), 0,
[](std::size_t sum, const std::string& s) {
return sum + s.size();
});
return length + vec.size();
}
template<size_t N>
constexpr std::array<char, N+1> join_to_array(const std::vector<std::string>& vec, char delimiter) {
std::string result = std::accumulate(std::next(vec.begin()), vec.end(),
vec[0],
[&delimiter](const std::string& a, const std::string& b) {
return a + delimiter + b;
});
std::array<char, N+1> arr = {};
int i = 0;
for (auto c : result) {
arr[i++] = c;
}
return arr;
}
constexpr std::vector<std::string> getWords() {
return { "one", "two", "three" };
}
int main()
{
constexpr auto arr2 = join_to_array<join_length(getWords(), ';')>(getWords(), ';');
static_assert(std::string(&arr2[0]) == "one;two;three");
std::cout << &arr2[0] << "\n";
}
std::string
不是字面类型(literal type)。 - Piotr Skotnickistd::string
成为constexpr?stackoverflow上有几种编译时字符串实现。如果你已经理解了错误信息并且只有字面值类型可以成为constexpr,那么询问非文字类型是否可以成为constexpr有何意义?此外,有几个原因可能需要一个constexpr实例,因此我建议您澄清您的问题。 - Piotr Skotnickiconstexpr
的字符串。std::string
不是其中之一。 - tenfour