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

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