Vec*_*tor 142 stdstring constexpr c++11
使用C++ 11,Ubuntu 14.04,GCC默认工具链.
此代码失败:
constexpr std::string constString = "constString";
Run Code Online (Sandbox Code Playgroud)
错误:constexpr变量'constString'的类型'const string {aka const std :: basic_string}'不是文字...因为......'std :: basic_string'有一个非平凡的析构函数
是否有可能使用std::string
的constexpr
?(显然不是......)如果是这样,怎么样?是否有另一种方法在一个字符串中使用字符串constexpr
?
ten*_*our 139
不,你的编译器已经给你一个全面的解释.
但你可以这样做:
constexpr char constString[] = "constString";
Run Code Online (Sandbox Code Playgroud)
在运行时,这可以用于std::string
在需要时构造.
Jos*_*son 112
在C++ 17中,您可以使用string_view
:
constexpr std::string_view sv = "hello, world";
Run Code Online (Sandbox Code Playgroud)
A string_view
是类似string
对象,充当对任何char
对象序列的不可变的非拥有引用.
neu*_*ont 16
由于问题是非平凡的析构函数,因此如果从中删除析构函数std::string
,则可以定义constexpr
该类型的实例.像这样
struct constexpr_str {
char const* str;
std::size_t size;
// can only construct from a char[] literal
template <std::size_t N>
constexpr constexpr_str(char const (&s)[N])
: str(s)
, size(N - 1) // not count the trailing nul
{}
};
int main()
{
constexpr constexpr_str s("constString");
// its .size is a constexpr
std::array<int, s.size> a;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
mar*_*inj 13
C++20 是朝着可以在编译时使用的方向迈出的一步std::string
,但 P0980 不允许您编写像问题中那样的代码:
constexpr std::string constString = "constString";
Run Code Online (Sandbox Code Playgroud)
原因是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
Run Code Online (Sandbox Code Playgroud)
这是因为它试图进行不允许的非瞬态分配 - 这意味着分配到已编译二进制文件的数据段中。
在p0784r1中,在“非瞬态分配”段落中,您可以发现有一个计划允许将瞬态内存转换为静态内存(强调我的):
评估完成时尚未释放的存储怎么办?我们可以不允许这样做,但确实存在令人信服的用例,这可能是可取的。例如,这可能是更灵活的“字符串文字”类的基础。因此,我们建议,如果非瞬态常量表达式分配有效(接下来将进行描述),则分配的对象将提升为静态存储持续时间。
有一种方法可以将瞬态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";
}
Run Code Online (Sandbox Code Playgroud)
C ++ 20将添加constexpr
字符串和向量
显然已接受以下提议:http : //www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0980r0.pdf并添加了以下构造函数:
// 20.3.2.2, construct/copy/destroy
constexpr
basic_string() noexcept(noexcept(Allocator())) : basic_string(Allocator()) { }
constexpr
explicit basic_string(const Allocator& a) noexcept;
constexpr
basic_string(const basic_string& str);
constexpr
basic_string(basic_string&& str) noexcept;
Run Code Online (Sandbox Code Playgroud)
除了所有/大多数方法的constexpr版本。
自GCC 9.1.0起不提供支持,以下内容无法编译:
#include <string>
int main() {
constexpr std::string s("abc");
}
Run Code Online (Sandbox Code Playgroud)
与:
g++-9 -std=c++2a main.cpp
Run Code Online (Sandbox Code Playgroud)
错误:
error: the type ‘const string’ {aka ‘const std::__cxx11::basic_string<char>’} of ‘constexpr’ variable ‘s’ is not literal
Run Code Online (Sandbox Code Playgroud)
std::vector
讨论在:无法创建constexpr std :: vector
在Ubuntu 19.04中测试。