(Translated by https://www.hiragana.jp/)
C++17 - 維基百科,自由的百科全書 とべいたり內容

C++17

本頁使用了標題或全文手工轉換
維基百科ひゃっか自由じゆうてき百科全書ひゃっかぜんしょ

C++17 C++規格きかく委員いいんかい於2017ねん制定せいていてき規格きかく(ISO/IEC 14882),せっがえC++14規格きかくかむC++20規格きかくだい

歷史れきし

[編輯へんしゅう]

ざいC++規格きかく委員いいんかい制定せいてい此次てきさんねん規格きかくまえ,C++17規格きかくてき發布はっぷ確定かくていてきざい這段ちゅう,C++17草案そうあん(draft)也被たたえためC++1zせい如C++11草案そうあんめいC++0xあるC++1x,C++14草案そうあんめいC++1y。C++17規格きかく於2017ねん3がつ完成かんせい國際こくさい規格きかく草案そうあん(Draft International Standard DIS)階段かいだんなみ同年どうねん12がつ完成かんせい最終さいしゅう規格きかく發布はっぷ。17規格きかくたいC++語法ごほう進行しんこうりょうきょうなみたい規格きかくいた進行しんこうりょう些許おさむあらため,如給<algorithm>くらちゅう演算えんざんほう增加ぞうかりょう執行しっこう策略さくりゃくexecution以支援しえん平行へいこう計算けいさん

しんこうのう

[編輯へんしゅう]
  • 靜態せいたい斷言だんげんstatic_assert需提供出きょうしゅつ錯資訊[1]
  • うつりじょ trigraphs[2][3]
  • 具有ぐゆうばん形式けいしきてきばん(template template)さんすう允許いんきょ使用しよう typename(これぜん允許いんきょ使用しよう class)[4]
  • std::uncaught_exceptions だい std::uncaught_exception[5][6]
  • へんちょうさんすうばんてきFolding運算うんざん[6][7]
  • 容器ようきそん操作そうさ表示ひょうじ方法ほうほうてき統一とういつ(Uniform container access)[8][9]
  • 連續れんぞくがた迭代(Contiguous Iterators)[8][10]
  • しんぞう特殊とくしゅ數學すうがくはこしき[11]
  • 引進Library Fundamentals TS Iなかてき內容[12]

類別るいべつばんてきばんさんすう推導

[編輯へんしゅう]

かたぎいたるい构造式能しきのう自動じどう推導ばんさんすうてきがた别(Class template argument deduction, CTAD)。れい允許いんきょpair(5.0, false) がわpair<double,bool>(5.0, false)

template <typename T = float>
struct MyContainer {
  T val;
  MyContainer() : val{} {}
  MyContainer(T val) : val{val} {}
  // ...
};
MyContainer c1 {1}; // OK MyContainer<int>
MyContainer c2; // OK MyContainer<float>

にんなん指定してい變數へんすうある變數へんすうばんてきはつはじめてき宣告せんこく,其宣告せんこくてきがた别是類別るいべつばん可能かのう cv 限定げんていてき)。如std::pair p(2, 4.5); // deduces to std::pair<int, double> p(2, 4.5); newひょうたちしき,如template<class T>struct A{ A(T, T);}; auto y = new A{1, 2}; // allocated type is A<int>

ようauto宣告せんこくかた别模ばんさんすう

[編輯へんしゅう]

依據いきょautoてき推到規則きそくざい允許いんきょがた别的かた别模ばんさんすう情況じょうきょうしたがえじつさんがた别推導出どうしゅつばんさんすう

template <auto... seq>
struct my_integer_sequence {
  // Implementation here ...
};

// Explicitly pass type `int` as template argument.
auto seq = std::integer_sequence<int, 0, 1, 2>();
// Type is deduced to be `int`.
auto seq2 = my_integer_sequence<0, 1, 2>();

すり疊表たたみおもてたちしき

[編輯へんしゅう]

すり疊表たたみおもてたちしきざい運算うんざんじょう執行しっこうばんさんすうつつみてき展開てんかい計算けいさん

  • 單元たんげんすりたたみかたち如 (... op e) or (e op ...)ひょうたちしき,其中 op すりたたみ運算うんざん,e 展開てんかいてきばんさんすうつつみ
  • 二元にげんすりたたみかたち如(e1 op ... op e2)ひょうたちしき, 其中 op すりたたみ運算うんざん,e1あるe2 展開てんかいてきばんさんすうつつみ
template <typename... Args>
bool logicalAnd(Args... args) {
    // Binary folding.
    return (true && ... && args);
}
bool b = true;
bool& b2 = b;
logicalAnd(b, b2, true); // == true

template <typename... Args>
auto sum(Args... args) {
    // Unary folding.
    return (... + args);
}
sum(1.0, 2.0f, 3); // == 6.0

だいくくごうはつはじめくしれつてきしんてき自動じどう推導規則きそく

[編輯へんしゅう]

以前いぜんauto x {3}; はた推導ためstd::initializer_list<int>, 現在げんざい推導ためint[13][14]

auto x1 {1, 2, 3}; // error: not a single element
auto x2 = {1, 2, 3}; // x2 is std::initializer_list<int>
auto x3 {3}; // x3 is int
auto x4 {3.0}; // x4 is double

constexpr lambda

[編輯へんしゅう]
auto identity = [](int n) constexpr { return n; };
static_assert(identity(123) == 123);

constexpr auto add = [](int x, int y) {
  auto L = [=] { return x; };
  auto R = [=] { return y; };
  return [=] { return L() + R(); };
};

static_assert(add(1, 2)() == 3);

constexpr int addOne(int n) {
  return [n] { return n + 1; }();
}

static_assert(addOne(1) == 2);

Lambdaはこしきちゅう按值擷取this指標しひょう

[編輯へんしゅう]

以前いぜんthis指標しひょうざいlambdaはこしきただのう參考さんこう擷取。現在げんざい *this 擷取對象たいしょうてき副本ふくほん,而 this (C++11)繼續けいぞく擷取參考さんこう

struct MyObj {
  int value {123};
  auto getValueCopy() {
    return [*this] { return value; };
  }
  auto getValueRef() {
    return [this] { return value; };
  }
};
MyObj mo;
auto valueCopy = mo.getValueCopy();
auto valueRef = mo.getValueRef();
mo.value = 321;
valueCopy(); // 123
valueRef(); // 321

くだり內變すう

[編輯へんしゅう]

過去かこせきかぎinline可用かよう於函しき宣告せんこく現在げんざい也可以用於變すう宣告せんこく表示ひょうじはこしきある定義ていぎ定義ていぎただし內容必須ひっす完全かんぜんしょうどうつぎ。這允許いんきょざいしるべあたま檔中定義ていぎいちぎょう內變すう

  • くだり內的はこしきある變數へんすう必須ひっすざいへんやく單元たんげん內可たちただし一定いっていざい訪問ほうもんてんまえ
  • ざいまいへんやく單元たんげんなかこれぎょう宣告せんこくてき
  • くだり內變すう必須ひっす靜態せいたい記憶きおくたいるい靜態せいたい成員せいいんある命名めいめい空間くうかん作用さよういき變數へんすう),不能ふのうよう於塊作用さよういき變數へんすうあるはこしき作用さよういき變數へんすう
struct S {
  S() : id{count++} {}
  ~S() { count--; }
  int id;
  static inline int count{0}; // declare and initialize count to 0 within the class
};

じょうてき命名めいめい空間くうかん

[編輯へんしゅう]

如下:[14][15]

namespace A {
  namespace B {
    namespace C {
      int i;
    }
  }
}

//The code above can be written like this:

namespace A::B::C {
  int i;
}

結構けっこう繫結

[編輯へんしゅう]

變數へんすう定義ていぎはつはじめ允許いんきょがた auto [ x, y, z ] = expr;,其中exprてきもとくみ類似るいじてき對象たいしょう包括ほうかつstd::tuple, std::pair, std::arrayとう聚合結構けっこう

using Coordinate = std::pair<int, int>;
Coordinate origin() {
  return Coordinate{0, 0};
}

const auto [ x, y ] = origin();
x; // == 0
y; // == 0

std::unordered_map<std::string, int> mapping {
  {"a", 1},
  {"b", 2},
  {"c", 3}
};

// Destructure by reference.
for (const auto& [key, value] : mapping) {
  // Do something with key and value
}

おびはつはじめてき選擇せんたくじゅつ

[編輯へんしゅう]

ifswitchじゅつ允許いんきょ如下てき變數へんすう宣告せんこくはつはじめ

{
  std::lock_guard<std::mutex> lk(mx);
  if (v.empty()) v.push_back(val);
}
// vs.
if (std::lock_guard<std::mutex> lk(mx); v.empty()) {
  v.push_back(val);
}

Foo gadget(args);
switch (auto s = gadget.status()) {
  case OK: gadget.zip(); break;
  case Bad: throw BadFoo(s.message());
}
// vs.
switch (Foo gadget(args); auto s = gadget.status()) {
  case OK: gadget.zip(); break;
  case Bad: throw BadFoo(s.message());
}

constexpr if

[編輯へんしゅう]
//适用场景1:简化ばんへんとくてきうつしほう
template <typename T>
constexpr bool isIntegral() {
  if constexpr (std::is_integral<T>::value) {
    return true;
  } else {
    return false;
  }
}
static_assert(isIntegral<int>() == true);
static_assert(isIntegral<char>() == true);
static_assert(isIntegral<double>() == false);
struct S {};
static_assert(isIntegral<S>() == false);

//适用场景2:编写变参ばん函数かんすう
template<int N, int...Ns>
int Sum()
{
  if constexpr(0 == sizeof...(Ns))
    return N;
  else
    return N+Sum<Ns...> ();
}

//使用しよう场景3:がえだいenable_if。编写ばん函数かんすう时,经常よう使用しようenable_if语句らい进行せい态类がた检查,证模ばん输入てき类型满足ぼう要求ようきゅう
template <typename T>
bool IsOdd(T input){
 if constexpr (std::is_integral<T>::value) //
   return static_cast<bool>(input % 2);
}

utf8字面じめんりょう

[編輯へんしゅう]

如下:[6][16]

char x = u8'x';

れつ舉型别變すう直接ちょくせつようだいくくごうはつはじめ

[編輯へんしゅう]
enum byte : unsigned char {};
byte b {0}; // OK
byte c {-1}; // ERROR
byte d = byte{1}; // OK
byte e = byte{256}; // ERROR

fallthrough, nodiscard, maybe_unused特性とくせい

[編輯へんしゅう]

C++17 引入りょう3特性とくせい(attribute): fallthrough, nodiscard, maybe_unused.

//fallthrough指示しじ编译直通ちょくつういち个switch语句:
switch (n) {
  case 1: 
    // ...
    [[fallthrough]]
  case 2:
    // ...
    break;
}

//nodiscard引发いち警告けいこくとう具有ぐゆう该特せいてき函数かんすうある类的かえしかい值被ゆるがせりゃく
[[nodiscard]] bool do_something() {
  return is_success; // true for success, false for failure
}

do_something(); // warning: ignoring return value of 'bool do_something()',
                // declared with attribute 'nodiscard'

// Only issues a warning when `error_info` is returned by value.
struct [[nodiscard]] error_info {
  // ...
};

error_info do_something() {
  error_info ei;
  // ...
  return ei;
}

do_something(); // warning: ignoring returned value of type 'error_info',
                // declared with attribute 'nodiscard'

//maybe_unusedつげ诉编译器变量あるさんすう可能かのう使用しよう
void my_callback(std::string msg, [[maybe_unused]] bool error) {
  // Don't care if `msg` is an error message, just log it.
  log(msg);
}

__has_include運算うんざん

[編輯へんしゅう]

__has_include運算うんざんようざい#if #elifひょうたちしき,以檢查是一個標頭檔或原始檔可否包含。

//しもれいゆう两个しょうどう作用さようてき头文けん,如果主文しゅぶんけん不能ふのう包含ほうがん, 就使用しようbackup/experimental头文けん
#ifdef __has_include
#  if __has_include(<optional>)
#    include <optional>
#    define have_optional 1
#  elif __has_include(<experimental/optional>)
#    include <experimental/optional>
#    define have_optional 1
#    define experimental_optional
#  else
#    define have_optional 0
#  endif
#endif

//也可以用ざい不同ふどう位置いち不同ふどう名字みょうじただし具有ぐゆうしょうどう地位ちいてき头文けんてき包含ほうがん
#ifdef __has_include
#  if __has_include(<OpenGL/gl.h>)
#    include <OpenGL/gl.h>
#    include <OpenGL/glu.h>
#  elif __has_include(<GL/gl.h>)
#    include <GL/gl.h>
#    include <GL/glu.h>
#  else
#    error No suitable OpenGL headers found.
# endif
#endif

std::variant

[編輯へんしゅう]

std::variantいたるいじつ做了がた别安全的ぜんてきunion

std::variant<int, double> v{ 12 };
std::get<int>(v); // == 12
std::get<0>(v); // == 12
v = 12.0;
std::get<double>(v); // == 12.0
std::get<1>(v); // == 12.0

std::optional

[編輯へんしゅう]

std::optional類別るいべつばん可能かのう包含ほうがん一個值或者可能不包含值:

std::optional<std::string> create(bool b) {
  if (b) {
    return "Godzilla";
  } else {
    return {};//あるもの return std::nullopt;
  }
}

create(false).has_value();//かえしかいtrueあるfalse
*create(false);//かえしかい值;如果无值,则返かいT()
create(false).value_or("empty"); // == "empty"
create(true).value(); // == "Godzilla"
// optional-returning factory functions are usable as conditions of while and if
if (auto str = create(true)) {
  // ...
}

std::anyいたるいがた别安全的ぜんてき包含ほうがんにんなんがた别的值:

std::any x {5};
x.has_value() // == true
std::any_cast<int>(x) // == 5
std::any_cast<int&>(x) = 10;
std::any_cast<int>(x) // == 10

std::string_view

[編輯へんしゅう]

std::string_viewるいようゆうもと序列じょれつてき情況じょうきょう讀取よみと其值:[17]

// Regular strings.
std::string_view cppstr {"foo"};
// Wide strings.
std::wstring_view wcstr_v {L"baz"};
// Character arrays.
char array[3] = {'b', 'a', 'r'};
std::string_view array_v(array, std::size(array));

std::string str {"   trim me"};
std::string_view v {str};
v.remove_prefix(std::min(v.find_first_not_of(" "), v.size()));
str; //  == "   trim me"
v; // == "trim me"

std::string_view提供ていきょうc_str()成員せいいんはこしき

std::invokeよう喚起かんき喚起かんき對象たいしょう」。

template <typename Callable>
class Proxy {
  Callable c;
public:
  Proxy(Callable c): c(c) {}
  template <class... Args>
  decltype(auto) operator()(Args&&... args) {
    // ...
    return std::invoke(c, std::forward<Args>(args)...);
  }
};
auto add = [](int x, int y) {
  return x + y;
};
Proxy<decltype(add)> p {add};
p(1, 2); // == 3

std::applystd::tupleさんすう應用おうよう於可喚起かんき對象たいしょう

auto add = [](int x, int y) {
  return x + y;
};
std::apply(add, std::make_tuple(1, 2)); // == 3

std::filesystem

[編輯へんしゅう]

std::filesystem操作そうさ檔案、目錄もくろくみちみち[18]

const auto bigFilePath {"bigFileToCopy"};
if (std::filesystem::exists(bigFilePath)) {
  const auto bigFileSize {std::filesystem::file_size(bigFilePath)};
  std::filesystem::path tmpPath {"/tmp"};
  if (std::filesystem::space(tmpPath).available > bigFileSize) {
    std::filesystem::create_directory(tmpPath.append("example"));
    std::filesystem::copy_file(bigFilePath, tmpPath.append("newFile"));
  }
}

std::byteがた别既もとかた别,也不算術さんじゅつがた别,實際じっさいじょうれつ舉型别:

std::byte a {0};
std::byte b {0xFF};
int i = std::to_integer<int>(b); // 0xFF
std::byte c = a & b;
int j = std::to_integer<int>(c); // 0

maps sets じょうさら有效ゆうこうりつ移動いどう節點せってん

[編輯へんしゅう]

れいひらき銷的節點せってん操作そうさ[19][8]

//Moving elements from one map to another:
std::map<int, string> src {{1, "one"}, {2, "two"}, {3, "buckle my shoe"}};
std::map<int, string> dst {{3, "three"}};
dst.insert(src.extract(src.find(1))); // Cheap remove and insert of { 1, "one" } from `src` to `dst`.
dst.insert(src.extract(2)); // Cheap remove and insert of { 2, "two" } from `src` to `dst`.
// dst == { { 1, "one" }, { 2, "two" }, { 3, "three" } };

//Inserting an entire set:
std::set<int> src {1, 3, 5};
std::set<int> dst {2, 4, 5};
dst.merge(src);
// src == { 5 }
// dst == { 1, 2, 3, 4, 5 }

//Inserting elements which outlive the container:
auto elementFactory() {
  std::set<...> s;
  s.emplace(...);
  return s.extract(s.begin());
}
s2.insert(elementFactory());

//Changing the key of a map element:
std::map<int, string> m {{1, "one"}, {2, "two"}, {3, "three"}};
auto e = m.extract(2);
e.key() = 4;
m.insert(std::move(e));
// m == { { 1, "one" }, { 3, "three" }, { 4, "two" } }

並列へいれつ演算えんざんほう

[編輯へんしゅう]

許多きょたSTL演算えんざんほう,如copy, find sort,支援しえん並列へいれつ執行しっこう政策せいさく:seq, par, par_unseq, unseq分別ふんべつ表示ひょうじ"sequentially", "parallel", "parallel unsequenced", "unsequenced".[20]

std::vector<int> longVector;
// Find element using parallel execution policy
auto result1 = std::find(std::execution::par, std::begin(longVector), std::end(longVector), 2);
// Sort elements using sequential execution policy
auto result2 = std::sort(std::execution::seq, std::begin(longVector), std::end(longVector));

注釋ちゅうしゃく

[編輯へんしゅう]
  1. ^ N3928: Extending static_assert, v2 (Walter E. Brown) (PDF). [2015-07-16]. (原始げんし內容そん (PDF)於2015-08-11). 
  2. ^ N3981: Removing trigraphs??! (Richard Smith). 2014-05-06 [2015-07-16]. (原始げんし內容そん於2018-07-09). 
  3. ^ IBM comment on preparing for a Trigraph-adverse future in C++17ぺーじめんそん檔備份そんあみぎわもう檔案かん), IBM paper N4210, 2014-10-10. Authors: Michael Wong, Hubert Tong, Rajan Bhakta, Derek Inglis
  4. ^ N4051: Allow typename in a template template parameter (Richard Smith). [2015-07-16]. (原始げんし內容そん於2015-08-11). 
  5. ^ N4259: Wording for std::uncaught_exceptions (Herb Sutter) (PDF). [2015-07-16]. (原始げんし內容 (PDF)そん檔於2014-11-29). 
  6. ^ 6.0 6.1 6.2 New core language papers adopted for C++17. [2015-07-16]. (原始げんし內容そん於2015-04-27). 
  7. ^ N4295: Folding expressions (Andrew Sutton, Richard Smith). [2015-07-16]. (原始げんし內容そん於2015-04-04). 
  8. ^ 8.0 8.1 8.2 New standard library papers adopted for C++17. [2015-07-16]. (原始げんし內容そん於2014-11-29). 
  9. ^ N4280: Non-member size() and more (Riccardo Marcangelo) (PDF). [2015-07-16]. (原始げんし內容そん (PDF)於2015-03-09). 
  10. ^ N4284: Contiguous Iterators (Jens Maurer). [2015-07-16]. (原始げんし內容そん檔於2014-11-29). 
  11. ^ Mathematical Special Functions for C++17, v5 (PDF). [2016-08-02]. (原始げんし內容そん (PDF)於2016-04-05). 
  12. ^ Adopt Library Fundamentals V1 TS Components for C++17 (R1). [2016-08-02]. (原始げんし內容そん於2016-04-05). 
  13. ^ N3922: New Rules for auto deduction from braced-init-list (James Dennett). [2015-07-16]. (原始げんし內容そん於2015-08-10). 
  14. ^ 14.0 14.1 Updates to my trip report. [2015-07-16]. (原始げんし內容そん於2015-03-19). 
  15. ^ N4230: Nested namespace definition (Robert Kawulak, Andrew Tomazos). [2015-07-16]. (原始げんし內容そん於2015-08-03). 
  16. ^ N4267: Adding u8 character literals (Richard Smith). [2015-07-16]. (原始げんし內容そん於2015-10-28). 
  17. ^ std::basic_string_view - cppreference.com. en.cppreference.com. [2016-06-23]. (原始げんし內容そん於2016-06-17). 
  18. ^ Filesystem Library Proposal (Beman Dawes). [2016-08-02]. (原始げんし內容そん於2016-07-20). 
  19. ^ N4279: Improved insertion interface for unique-key maps (Thomas Köppe). [2015-07-16]. (原始げんし內容そん於2015-04-27). 
  20. ^ The Parallelism TS Should be Standardized. [2016-08-02]. (原始げんし內容そん於2016-04-05).