C++17新增特性
in Cplusplus Pageviews
cplusplus语言特性
If Statements with initializer
带初始化的If
语句
std::map<std::string, int> map;
map["a"] = 1;
map["b"] = 2;
if (auto ret = map.begin(); ret != map.end()) {
std::cout << ret->first << ": " << ret->second;
}
Constexpr if
在该语句中,条件的值必须是可以按语境转换到bool
类型的转换常量表达式。若其值为true
,则舍弃false
分支语句,否则舍弃true
语句。
template<typename T>
void ConstexprIf(T value) {
if constexpr (std::is_integral_v<T>) {
std::cout << "is integral" << std::endl;
} else {
static_assert(false, "T必须是整型");
}
}
属性说明符
[[fallthrough]]
指示出从前一标号直落是有意义的,而发生直落给出告警的编译器不应该诊断它。
switch (device.status()) {
case sleep:
device.wake();
[[fallthrough]];
case ready:
device.run();
break;
case bad:
handle_error();
break;
}
之前编译器会通告没有break的告警,在C++17后使用fallthrough
属性就可以消除这个警告了。
[[maybe_unused]]
可以用来消除未使用的函数或变量编译器发出的告警。
[[maybe_unused]] bool unusedVariable = true;
[[maybe_unused]] uint32_t UnusedFunction()
{
return 0;
}
[[nodiscard]]
如果你的某个函数返回值特别重要,希望使用者不要忽略,可以添加这个属性,在编译的时候如果函数使用者没有使用返回值将会产生一个告警;
[[nodiscard]] bool function()
{
return true;
}
[[deprecated]]
提示允许使用声明有此属性的名称或实体,但因为一些原因不被鼓励使用,一般用在即将废弃的函数,但是还有老用户使用了这个函数;
[[deprecated("test deprecated")]] bool function()
{
return true;
}
[[noreturn]]
用来告知函数没有返回值
[[noreturn]] void function() {
}
inline变量
inline 变量解决全局变量在头文件中定义之后多处使用产生符号定义错误。
// 以前会报错
// test.h
int test = 10;
// test1.cpp
void fun1()
{
test = 20;
}
// test2.cpp
void fun2()
{
test = 30;
}
// 重定义错误解决办法
// test.h
extern int test;
// test.cpp
int test = 10;
C++17之后引入的inline
变量使得全局变量可以直接在头文件中声明定义。
// test.h
inline int test = 10;
string_view
string_view
相对于string
来说就是一个只读的string
,string_view
的赋值操作的空间成本和时间成本远远胜于string
,string_view
的赋值特别像一个指针的赋值,一般来说在以情况使用string_view
比较合适。
// 常量string
const string str = "hello world!";
// string_view比较合适
constexpr string_view str = "hello world!";
// 函数参数
void fun(const string &str)
{
}
// string_view
void fun(const string_view &str)
{
}
any
any
是一个可以用于任何类型的单个值的类型安全容器。
std::any Int = 10;
std::any Double = 1.234;
std::any String = std::string_view("hello world!");
std::vector<std::any> anys{Int, Double, String};
std::cout << std::any_cast<int>(Int) << std::endl;
std::cout << std::any_cast<double>(Double) << std::endl;
std::cout << std::any_cast<std::string_view>(String) << std::endl;
std::any a = 1;
if (a.has_value()) {
std::cout << a.type().name() << std::endl;
}
a.reset();
if (!a.has_value) {
std::cout << "no value" << std::endl;
}
optional
在返回值是string
或者int
等出现错误之后非常隐式的表达的地方,使用std::optional
就可以帮你解决这一问题;另外就是当对外暴漏了一个结构体,但是里面有些参数是可选项,那optional
就派上用场了。
// 1
[[nodiscard]] std::optional<int> TestOptional1()
{
if (ok) {
return 100;
} else {
return std::nullopt;
}
}
[[nodiscard]] std::optional<string> TestOptional2()
{
if (ok) {
return "hello world!";
} else {
return std::nullopt;
}
}
// optional
auto res = TestOptional1();
if (res.has_value()) {
// success
} else {
// fail
}
auto ret = TestOptional2().value_or("");
// 2
struct MyStruct {
std::optional<int> width;
std::optional<int> height;
int fps{30};
};
void DoSomething(const MyStruct &myStruct)
{
if (myStruct.width.has_value()) {
// ...
}
if (myStruct.height.has_value()) {
// ...
}
}
variant
variant
是一个类型安全的联合体,variant
的一个实例在任意时刻要么保有其一个可选类型之一的值,要么在错误的情况下无值。variant
不容许保有引用,数组,或类型void
,空variant
可以使用std::variant<std::monostate>
。
struct SystemProxyConfig {
bool isFile;
};
struct CustomProxyConfig {
bool isFile;
std::string pathOrContent;
};
std::variant<SystemProxyConfig, CustomProxyConfig> config;
config = SystemProxyConfig{false};
if (std::get_if<CustomProxyConfig>(&config)) {
// 成功
CustomProxyConfig customCfg = std::get<CustomProxyConfig>(config);
} else {
// 失败
SystemProxyConfig systemCfg = std::get<SystemProxyConfig>(config);
}
execution
execution
为c++stl
算法库提供了一种算法的执行策略设置,目前支持的策略:
sequenced_policy
(顺序执行策略)parallel_polixy
(并行执行策略)parallel_unsequenced_policy
(并行及无序执行策略)unsequenced_policy
(无序执行策略)
std::vector<int> testExecution{1,2,3,4,58,23,56,78,55,66,77,9,1,0,45,1111,45,13,57};
auto it1 = std::find(std::exexution::seq, testExecution.begin(), testExecution.end(), 5);
auto it2 = std::find(std::exexution::par, testExecution.begin(), testExecution.end(), 5);
auto it3 = std::find(std::exexution::par_unseq, testExecution.begin(), testExecution.end(), 5);