C++17 新功能介绍

C++17 新功能介绍

std::any

  1. 说明

    • 用来包裹任何类型的容器, 行为类似于void *, 但更安全, 有专门的类型转换api,转换的类型不匹配时会有转换异常抛出
    • 头文件 <any>
  2. 示例代码

std::any any = 0; // any = int(0)

std::cout << std::any_cast<int>(any) << std::endl; /// 0
std::cout << std::any_cast<double>(any) << std::endl; /// std::bad_any_cast异常

any = 1.0; /// 此时any又变为 double(1.0)

std::optional

  1. 说明

    • 可选值对象, 表示某种类型的具体值或者空值, 行为类似指针, 但内存分配在栈上
    • 头文件 <optional>
  2. 示例代码

std::optional<int> make_int(int a, int b) {
  return a < b ? std::optinal(a + b): std::optional<int>();
}

auto n = make_int(1, 2); /// n = 3

if (n) {
  std::cout << n.value() << std::endl;
}

n = make_int(5, 1); /// n = null

std::cout << n.value_or(9) << std::endl; // 输出 9


std::variant

  1. 说明

    • 类型安全的联合体对象
    • 头文件 <variant>
  2. 示例代码

std::variant<int, char, bool> var;

var = 12; // var 为int(12)

std::get<int>(var); // -> 12
std::get<0>(var); // -> 12

var.index(); // -> 0

var = 'A'; // var 为char('A')

std::get<char>(var); // -> 'A'
std::get<1>(var); // -> 'A'
var.index(); // -> 1

var = true; /// var为bool(true)
std::get<bool>(var); // -> true
std::get<2>(var); // -> true
var.index(); // -> 2

std::filesystem

  1. 说明

    • 原boost::filesystem库, 文件系统操作, 包括文件/目录/软链接的增删改查
    • 头文件 <filesystem>
  2. 示例代码

std::string_view

  1. 说明

    • 指代字符串常量的类对象, 不会另外分配内存
    • 头文件 <string_view>
  2. 示例代码

/// 定义一个字符串常量打印函数
void print(std::string_view msg) {
  std::cout << msg << std:endl;
}

/// 使用
/// 1. 使用const char *做参数
print("Hello C string"); /// 虽然std::string做参数也能做到, 但是会执行字词内存拷贝用来构造一个std::string

/// 2. 使用std::string 做参数
std::string msg("Hello std::string");
print(msg); ///相当于 print(const std::string&)

std::literals

  1. 说明

    扩展的字面值, 使用原始字面值加特定后缀的方式可以直接创建某些特定的标准库类型

  2. 示例代码

using namespace std::literals;
// using namespace std::literals:string_literals
// using namespace std::literals:chrono_literals

auto str = "hello world"s; /// str 为std::string类型
auto seconds = 60s; /// seconds为std::chrono::seconds(60);
auto minutes = 10min; /// minutes 为 std::chrono::minutes(10);
auto hours = 2h; /// hours 为std::chrono::hour(2);

std::gcd / std::lcm

  1. 说明
    • std::gcd: 求两个整数的最大公约数
    • std::lcm: 求两个整数的最小公倍数
  2. 示例代码
auto gcd = std::gcd(6, 9); /// 3
auto lcm = std::lcm(6, 9); /// 18

std::invoke

  1. 说明

    • 使用不定参数的形式来调用可调用的对象
    • 头文件 <functional>
  2. 示例代码

int add(int a, int b) {
  return a + b;
}

struct One {
  
  void add(int a) {
    std::cout << number + a << std::endl;
  }
  
  int number;
};

///调用普通函数
std::cout << std::invoke(add, 1, 2) << std::endl;
///lambda表达式
std::cout << std::invoke([](std::string name) { 
	return "hello" + name;
}, "oyoung") << std::endl;
///类成员函数

One one{1000};

std::cout << std::invoke(&One::number, one) << std::endl; /// 相当于 one.number

std::apply

  1. 说明

    • 用于将 std::pair、std::tuple、std::array等类型的变量按对应位置作为可调用对象的参数
    • 头文件 <tuple>
  2. 示例代码

void show(std::string_view sv, char c) {
  std::cout << sv << ": " << c << std::endl;
}

void say_self(std::string_view name, int age, bool gender) {
  std::cout << "My name is " << name 
    				<< ", I'm " << age << (age > 1 ? "years old": "year old")
    				<< ", and I'm a " << (gender ? "boy": "girl") 
    				<< std::endl;
}

int main(int, char**) {
  
using namespace std::literals;

  std::map<std::string, int> map {
    {"A"s, 'A'},
    {"B"s, 'B'}
  };
  
  for(auto pair: map) {
    std::apply(show, pair); /// 等价于 show(pair.first, pair.second)
  }
  
  auto xiaoming = std::make_tuple("小明", 20, true);
  auto xiaohong = std::make_tuple("小红", 16, false);
  
  std::apply(say_self, xiaoming); /// 等价于 say_self("小明", 20, true)
  std::apply(say_self, xiaohong); /// 等价于 say_self("小红", 16, false)

  return 0;
}

嵌套命名空间

  1. 说明

    命名空间定义精简版

  2. 示例代码

/// C++17 之前需要这样写
namespace jdrv {
  namespace ros {
    namespace impl {
      /// ...
    }
  }
}

/// C++17可以这样写
namespace jdrv::ros::impl {
  
}

折叠表达式

  1. 说明

    使用...操作符来指代不定参数中的任意一个参数

  2. 示例代码

/// 判断所有参数是否都为真值
template<typename ...Args>
bool all(Args&& ...args) {
  return (... and args);
}

auto is_all_true = all(1 == 1, 2 < 3, 4 > 5); /// = all(true, true, false) => ((true and true) and false)

/// 打印多个值
template<typename ...Args> 
void print(Args&& ...args) {
  (std::cout << ... << args) << std::endl;
}

print('A', 0, 1.5, true); /// 打印: A01.51

类模板实参推导

  1. 说明
  2. 示例代码
/// C++17之前
std::pair<int, bool> pair(0, true);
auto p = new std::array<int>{0, 1, 2, 3};


/// C++17
std::pair pair(0, true); /// 相当于 std::make_pair(0, true);
auto p = new std::array{0, 1, 2, 3}; /// 相当于 new std::array<int>{0, 1, 2, 3};

结构化绑定(类似解构)

  1. 说明

    用来对std::pair, std::tuple, std::array对象进行解构

  2. 示例代码

/// std::pair
auto pair = std::pair(0, false);

auto [pf, ps] = pair; /// pf: 0, ps: false

/// std::tuple
auto tuple = std::make_tuple('A', true, 0, 1.0);
auto [t0, t1, t2, t3] = tuple; /// t0: 'A', t1: true, t2: 0, t3: 1.0

/// std::array

std::array<int, 2> array{100, 200};

auto [i0, i1] = array; // i0: 100, i1: 200

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章