我正在编写许多 string_view 擅长的解析器代码,并且已经开始喜欢这种类型。我最近读了 ArthurO'Dwyer 的文章std::string_view is aborrow type,他的结论是 string_view (和其他“借用类型”)可以使用,只要它们“...仅作为函数参数和 for 循环出现”控制变量。” (有几个例外)。
但是,我最近开始使用 string_view 作为将枚举转换为字符串(我经常使用)的函数的返回值,例如这个Compiler Explorer:
#include <iostream>
#include <string>
#include <array>
#include <algorithm>
enum class Color
{
red, green, blue, yellow,
last // Must be kept last
};
constexpr std::string_view toString(Color color);
// The rest would normally be in a .cpp file
using cts = std::pair<Color, std::string_view>;
constexpr std::array colorNames = {cts{Color::red, "red color"},
cts{Color::green, "green color"},
cts{Color::blue, "blue color"},
cts{Color::yellow, "yellow color"}};
static_assert(colorNames.size() …
Run Code Online (Sandbox Code Playgroud) 这个问题(和代码)的灵感来自 Jason Turner 的《C++ Weekly》一集:停止使用constexpr
(并使用此代替!)
假设下面的代码(编译器资源管理器)
我的理解是,在声明函数局部变量时,static constexpr
我保证该变量仅初始化一次(静态),并且如果编译器无法证明单线程访问(由于它是 constexpr),通常不需要任何线程安全开销。
但是c++标准能保证这一点吗?标准中是否有任何地方可以确保我该行static constexpr auto arr = getArr();
永远不会导致编译器添加互斥体或其他类型的线程保护?
Jason Turner 的剧集或这个 stackoverflow 问题都没有提到局部静态变量可能带来的线程安全开销,这就是我正在寻找明确答案的要点 - 最好通过指向标准。
所以需要明确的是:我可以确保arr
函数getVal()
在编译时初始化,而不需要任何线程同步吗?
constexpr auto getArr()
{
std::array<int,10> arr;
for (int i = 0; i < 10; ++i) {
arr[i] = i*2;
}
return arr;
}
auto getVal(int i)
{
static constexpr auto arr = getArr();
return arr[i] + 1;
}
int main()
{
return …
Run Code Online (Sandbox Code Playgroud) 假设有以下代码片段:
#include <optional>
struct MyStruct
{
// MyStruct(int a) : a(a) {}
int a;
};
int main()
{
std::optional<MyStruct> ms1 = std::make_optional<MyStruct>(1);
std::optional<MyStruct> ms2{2};
std::optional<MyStruct> ms3;
ms3.emplace(3);
std::optional<MyStruct> ms4(std::in_place, 4);
}
Run Code Online (Sandbox Code Playgroud)
这按预期使用 c++20 和 gcc 11.2 工作,所有这四种创建方法都在 clang 上编译失败(编译器资源管理器链接)
为了使其与 clang 一起工作,我需要取消注释构造函数。
我的主要问题是:clang 还是 gcc 哪个编译器是正确的?
后续问题:如果 clang 是正确的,是否有任何方法可以在可选中创建没有构造函数的结构,而不将结构复制到其中,例如std::optional<MyStruct> ms{MyStruct{3}}
?