すべおの開発者が䜿甚すべき8぀のC ++ 17機胜

日垞のコヌドに圱響を䞎える8぀の䟿利な倉曎に぀いお説明したす。 4぀の倉曎は蚀語自䜓に関係し、さらに4぀-暙準ラむブラリに関係したす。


すべおのC ++開発者が䜿甚すべき10のC ++ 11機胜の蚘事にも興味があるかもしれたせん。

謝蟞


ロシアのC ++ナヌザヌグルヌプ䌚議でのレポヌトからいく぀かの䟋を取り䞊げたした。そのためのオヌガナむザヌずスピヌカヌに感謝したす。 私は䟋を挙げたした



1.宣蚀時の分解eng。構造バむンディング



新しい構文を䜿甚しお、 std::pair 、 std::tupleおよび構造䜓を分解するず䟿利です。


 #include <string> struct BookInfo { std::string title; // In UTF-8 int yearPublished = 0; }; BookInfo readBookInfo(); int main() { //      title  year,     auto [title, year] = readBookInfo(); } 

C ++ 17では、宣蚀時の分解に制限がありたす。



宣蚀時の分解は、原則ずしお、任意のクラスを分解するこずができたすtuple_element 、 tuple_size 、およびget特殊tuple_elementするこずにより、ヒントを䞀床曞くだけget 。 詳现に぀いおは、 クラスぞのC ++ 17構造化バむンディングサポヌトの远加blog.tartanllama.xyzの蚘事を参照しおください。


宣蚀時の分解は、 std::map<>およびstd::unordered_map<>コンテナで、叀い.insert()メ゜ッドず2぀の新しいメ゜ッドで.insert()たす。



try_emplaceを䜿甚した分解の䟋ず、マップを暪断するずきのキヌ倀分解


 #include <string> #include <map> #include <cassert> #include <iostream> int main() { std::map<std::string, std::string> map; auto [iterator1, succeed1] = map.try_emplace("key", "abc"); auto [iterator2, succeed2] = map.try_emplace("key", "cde"); auto [iterator3, succeed3] = map.try_emplace("another_key", "cde"); assert(succeed1); assert(!succeed2); assert(succeed3); //    key  value   range-based for for (auto&& [key, value] : map) { std::cout << key << ": " << value << "\n"; } } 

2.テンプレヌトパラメヌタの自動出力


䞻なルヌル



テンプレヌトパラメヌタを自動的に衚瀺するための独自のヒントを䜜成できたす Automatic_deduction_guidesを参照しおください


興味深い機胜 initializer_list<>コンストラクタヌinitializer_list<> 、1぀の芁玠のリストでinitializer_list<>スキップされたす。 䞀郚のJSONラむブラリjson_spiritなどの堎合、これは臎呜的です。 再垰型ずSTLコンテナヌを䜿甚しないでください


 #include <vector> #include <type_traits> #include <cassert> int main() { std::vector v{std::vector{1, 2}}; //  vector<int>,   vector<vector<int>> static_assert(std::is_same_v<std::vector<int>, decltype(v)>); //    assert(v.size() == 2); } 

3.ネストされた名前空間の宣蚀


名前空間のネストを回避し、回避しない堎合は、次のように宣蚀したす。


 namespace product::account::details { // ...   ... } 

4.属性nodiscard、fallthrough、maybe_unused


䞻なルヌル



属性の詳现に぀いおは、蚘事「C ++ 17の属性を䜿甚する方法」を参照しおください。 ここに短い抜粋がありたす。

C ++では、switch構造䜓の各ケヌスの埌にブレヌクを远加する必芁があり、これは経隓豊富な開発者にずっおも忘れがちです。 フォヌルスルヌ属性は、空の呜什に接着できる救助に来たす。 実際、属性は空のステヌトメントに続くケヌスに接着されおいたす。


 enum class option { A, B, C }; void choice(option value) { switch (value) { case option::A: // ... case option::B: // warning: unannotated fall-through between // switch labels // ... [[fallthrough]]; case option::C: // no warning // ... break; } } 

この属性を利甚するには、GCCおよびClangに-Wimplicit-fallthrough譊告を含める必芁がありたす。 このオプションを有効にするず、フォヌルスルヌ属性を持たない各ケヌスで譊告が生成されたす。


パフォヌマンス芁件の高いプロゞェクトでは、少なくずも䞀郚のコンポヌネントでは䟋倖をスロヌしないこずを実践できたす。 そのような堎合、操䜜゚ラヌは、関数から返された戻りコヌドによっお報告されたす。 ただし、このコヌドをチェックするのを忘れるこずは非垞に簡単です。


 [[nodiscard]] std::unique_ptr<Bitmap> LoadArrowBitmap() { /* ... */ } void foo() { // warning: ignoring return value of function declared // with warn_unused_result attribute LoadArrowBitmap(); } 

たずえば、゚ラヌクラスを䜿甚する堎合、宣蚀で属性を1回指定できたす。


 class [[nodiscard]] error_code { /* ... */ }; error_code bar(); void foo() { // warning: ignoring return value of function declared // with warn_unused_result attribute bar(); } 

プログラマヌは、呌び出された関数の゚ラヌコヌドを栌玍するために、デバッグバヌゞョンでのみ䜿甚される倉数を䜜成するこずがありたす。 おそらくこれは単なるコヌド蚭蚈゚ラヌであり、戻り倀は垞に凊理する必芁がありたす。 ただし


 // !  ! auto result = DoSystemCall(); (void)result; //    unused variable assert(result >= 0); //   [[maybe_unused]] auto result = DoSystemCall(); assert(result >= 0); 

5.文字列パラメヌタヌのstring_viewクラス


ルヌル



string_viewがパラメヌタヌにのみ最適に䜿甚される理由の詳现に぀いおは、蚘事std :: string_viewは文字列の䞀時むンスタンスから構築される蚘事を参照しおください。

string_viewクラスstring_view 、远加のメモリ割り圓おなしでstd::stringずconst char*䞡方から簡単に構築できるずいう点で優れおいたす。 constexprのサポヌトもあり、std :: stringむンタヌフェむスを繰り返したす。 ただし、マむナスがありたすstring_view 、末尟にヌル文字が存圚string_viewこずは保蚌されたせん。


6.オプションのクラスずバリアント


optional<>およびvariant<>非垞に広いため、この蚘事ではそれらを完党に説明しようずはしたせん。 䞻なルヌル



オプションのサンプルコヌド


 // nullopt -     nullopt_t,   //  optional ( nullptr  ) std::optional<int> optValue = std::nullopt; // ...  optValue ... //   ,  -1 const int valueOrFallback = optValue.value_or(-1); 


バリアントを含むサンプルコヌドここでは、バリアントが異なる状態に異なるデヌタを持っおいる堎合に、いく぀かの状態の1぀を保存するためにバリアントを䜿甚


 struct AnonymousUserState { }; struct TrialUserState { std::string userId; std::string username; }; struct SubscribedUserState { std::string userId; std::string username; Timestamp expirationDate; LicenseType licenceType; }; using UserState = std::variant< AnonymousUserState, TrialUserState, SubscribedUserState >; 

メモリ管理ぞのアプロヌチにおけるバリアントの利点デヌタは、远加のメモリ割り圓おなしでバリアント型の倀フィヌルドに栌玍されたす。 これにより、バリアント型のサむズは、その構成に含たれる型に䟝存したす。 これは、32ビットプロセッサ䞊のサむズテヌブルのように芋える堎合がありたすただし、これは䞍正確です。


むラスト


7.関数std :: size、std :: data、std :: begin、std :: endを䜿甚したす



バむトを操䜜するためにGSLラむブラリC ++コアガむドラむンサポヌトラむブラリに䟝存する方が良い堎合がありたす。


8. std ::ファむルシステムを䜿甚する


䞻なルヌル



Bad Boost ::ファむルシステムずは䜕ですか 圌にはいく぀かの蚭蚈䞊の問題があるこずがわかりたした



経隓のあるプログラマなら誰でも、WindowsシステムずUNIXシステムのパス凊理の違いを認識しおいたす。



もちろん、ファむルシステムはそのような違いから抜象化し、プラットフォヌム固有の文字列ずナニバヌサルUTF-8の䞡方を簡単に操䜜できるようにしたす。



ボヌナスルヌルクランプ、int_to_stringおよびstring_to_intの再䜜成を停止


std :: clamp関数は、minおよびmax関数を補完したす。 䞊ず䞋の䞡方の意味を切り捚おたす。 同様のboost::clamp機胜は、C ++の以前のバヌゞョンで䜿甚できたす。


「クランプを再発明しない」ルヌルは䞀般化できたす。倧芏暡なプロゞェクトでは、䞞め、倀のトリミングなどのために小さな関数や匏を重耇させないでください。 -これをラむブラリに䞀床远加するだけです。


同様のルヌルは、文字列凊理タスクに察しお機胜したす。 文字列ず解析のための独自の小さなラむブラリを持っおいたすか 解析たたは数倀の曞匏蚭定はありたすか その堎合、実装をto_charsおよびfrom_chars呌び出しに眮き換えたす


to_charsおよびfrom_chars゚ラヌ凊理をサポヌトしたす。 次の2぀の倀を返したす。



アプリケヌションコヌドでぱラヌに察する反応の方法が異なる堎合があるため、ラむブラリずナヌティリティクラス内でto_charsおよびfrom_charsを呌び出す必芁がありたす。


 #include <utility> //    ,     0 // (   atoi,      ) template<class T> T atoi_17(std::string_view str) { T res{}; std::from_chars(str.data(), str.data() + str.size(), res); return res; } 


Source: https://habr.com/ru/post/J343622/


All Articles