この部分には通常、糖衣構文 (最適化されたライブラリ関数またはモジュールをカプセル化する)、およびコードをより簡潔で読みやすくするいくつかの関数とライブラリが含まれます。
1. 構造化バインディング
C++ 17 より前では、for ループを使用してマップ / unowned_map を走査する場合、中間変数 (通常は無意味) を宣言し、中間変数と最初と 2 番目のキーワードを通じてキーと値にアクセスする必要がありました。
C++17 では、配列、タプル、または構造体のメンバーを一連の変数にバインドする構造化バインディングが導入されています*
// 1.构建一个描述人的结构体
struct Person {
int age = 0;
std::string name;
};
// 2. 获得一个结构体对象,姓名:”ABC“,年龄:99
Person getPerson() {
return Person{99, "ABC"};
};
// 3. 结构化绑定
auto [age, name] = getStruct();
// C++ 17 以前遍历 map,声明无意义引用elem
for(const auto& elem : map){
const auto& key = elem.first;
const auto& value = elem.second;
std::cout << elem.first << ": " << elem.second << std::endl;
}
// C++ 17
for(const auto& [key, value]: map){
std::cout << key << ": " << val << std::endl;
}
* : 厳密に言えば、構造化バインディングの結果は変数ではありません。つまり、キーと値は変数ではなく、C++ 標準ではこれらを「エイリアス」と呼ぶため、ラムダ式でキャプチャできませんが、gcc はC++ 標準なので、次のコードは gcc でコンパイルできますが、clang ではコンパイルできません。
for(const auto& [key, value]: map){
[&key, &value]{
std::cout << key << ": " << value << std::endl;
}();
}
Clang をコンパイル フロント エンドとして使用する場合、ラムダ式をキャプチャしてコンパイルに合格するときに参照変数を明示的に導入できます。
for(const auto& [key, value]: map){
[&key = key, &value = value]{
std::cout << key << ": " << value << std::endl;
}();
}
しかし!この制限は C++20 では削除されたため、gcc と Clang の両方が C++20 標準の構造化バインディング オブジェクトをキャプチャできるようになりました。
2. std::tuple の暗黙的な導出
std::tuple の推論ガイド - cppreference.com
C++ 17 より前では、std::pair / std::tuple を構築するときに、データ型を指定するかstd::make_pair/std::make_tuple
関数を使用する必要がありましたが、C++ 17 ではstd::pair/std::tuple
演繹ルールが追加され、指定された型を表示できなくなりました。
// C++ 17 以前
std::pair<int, std::string> p1{99, "ABC"s};
auto p1 = std::make_pair(99, "ABC"s);
// C++ 17 pair的具体类型隐式声明
std::pair p3{99, "ABC"s};
3. constexpr の場合
if constexpr 文はコンパイル段階の if 判定文で、コンパイル段階でテンプレートパラメータの値に応じて該当する段落をコンパイルできるため、「パラダイムプログラミング」で使用できます。実行時にパフォーマンスが低下する可能性があります。C++17 コンパイル時の条件判断は、SFINAE メカニズムまたはテンプレートのオーバーロードを通じて実現する必要があります。
// C++ 17 使用变长参数模板 和 if constexpr 实现数字求和
template <int N, int... Ns>
auto sum()
{
if constexpr (0 == sizeof...(Ns))
return N;
else
return N + sum<Ns...>();
}
// 调用
sum<1, 2, 3>(); // returns 6
if constexpr 以前は、実行時の条件判定に通常の if ~ else が使用されていたため、汎用プログラミング では使用できませんでした。この合計の例では、if - else を使用して現在の可変長パラメーターの長さを決定することはできないため、単一のテンプレート パラメーターの場合を処理する追加の関数テンプレートを作成する必要があります。
// 一个模板参数时的函数模板?拗口
template<int N>
int sum()
{
return N;
}
// 模板参数 > 2 个时调用此模板
template <int N1, int N2, int... Ns>
int sum()
{
return N1 + sum<N2, Ns...>();
}
// 调用
sum<1, 2, 3>(); // returns 6
4. if / switch ステートメントでの初期化をサポート
C++ 17 では、if 文の条件判定の前に初期化文の追加がサポートされており、コードの読みやすさを向上させるために、if 文でのみ使用される変数をここで宣言します。
含むことができる
if (初始化语句; 条件) 语句 else 语句
switch (初始化语句; 条件) 语句
std::map<int, std::string> m;
std::mutex mx;
extern bool shared_flag; // guarded by mx
int demo()
{
if (auto it = m.find(10); it != m.end()) { return it->second.size(); }
if (char buf[10]; std::fgets(buf, 10, stdin)) { m[0] += buf; }
if (std::lock_guard lock(mx); shared_flag) { unsafe_ping(); shared_flag = false; }
if (int s; int count = ReadBytesWithSignal(&s)) { publish(count); raise(s); }
if (const auto keywords = {"if", "for", "while"};
std::ranges::any_of(keywords, [&tok](const char* kw) { return tok == kw; }))
{
std::cerr << "Token must not be a keyword\n";
}
}