yohhoyの日記

技術的メモをしていきたい日記

C++

std::shared_ptr型と->*演算子とstd::invoke関数

C++

C++標準ライブラリのスマートポインタ型std::shared_ptr<T>では->*演算子オーバーロードを提供しない(注:->はあるよ)。 #include <memory> struct X { int mf(); }; // メンバ関数ポインタ int (X::*pmf)() = &X::mf; // (通常)ポインタ型 X* p = new X; p->mf(); //</memory></t>…

std::generator<T/T&&/T&/const T&>

次期C++2b(C++23)標準ライブラリのコルーチンサポート型std::generator&ltRef>(→id:yohhoy:20220801)の第1テンプレートパラメータRefと、オブジェクトのコピー/ムーブの関係性についてメモ。まとめ: 利用側にconst参照を提供:const-lvalue参照const T&…

std::generator<R>

次期C++2b(C++23)標準ライブラリに追加されるstd::generator<R>クラステンプレートについてメモ。提案文書P2502R2よりコード引用:*1 // C++2b #include <functional> #include <generator> #include <range> #include <utility> std::generator<int> fib() { auto a = 0, b = 1; while (true) { co_yield st</int></utility></range></generator></functional></r>…

C++オブジェクト基本操作:Copyable/Movable/Swappable

C++

プログラミング言語C++のオブジェクトに対する基本操作として、コピー可能(copyable)/ムーブ可能(movable)/交換可能(swappable)の3段階が存在する。C++における最も原始的なオブジェクト操作は交換(swap)であり、ムーブ(move)、コピー(copy)の順にオブジェ…

演算子オーバーロード for 日付リテラル

C++

C++20標準ヘッダ <chrono> カレンダー(Calendar)ライブラリが提供する、日付リテラル表記用の/演算子オーバーロード一覧。ノート:年月日順で日付リテラルを述する場合、少なくとも年(year)フィールドは常に型を明示した方がトラブルリスク*1が小さい。/演算子は左結</chrono>…

-fimplicit-constexprオプション

gcc(g++) 12.1にて、inline関数に対して暗黙に constexpr 指定を行うコンパイルオプション -fimplicit-constexpr が導入された。同オプションはC++14/17/20言語仕様に対する独自拡張として機能する。 With each successive C++ standard the restrictions on…

std::expected<T, E>

次期C++2b(C++23)標準ライブラリに追加されるstd::expected<T, E>クラステンプレートについてメモ。 従来C++例外機構(throw文+try/catch構文)に代わり、関数の演算結果(T型)またはエラー情報(E型)を “値” として返す(return)ための部品。 C++17 std::optional<T>型の</t></t,>…

コンセプト制約式の構成:包摂関係 vs. コンパイル時間

C++

C++20コンセプトでは制約式(constraint-expression)を&&(conjunction)/||(disjunction)で組み合わせることで複雑な制約式を表現できる。一方で制約式が多数の原始制約(atomic constraint)から構成されるケースでは、包摂関係(subsumption relation)判定のた…

std::views::commonレンジアダプタの制約

C++20 RangeからC++17互換イテレータペアへの変換にはstd::views::commonレンジアダプタ(range adaptor)を利用する。ただしstd::ranges::basic_istream_viewなどムーブのみ/コピー不可なイテレータからなる一部Rangeは変換できない。*1 #include <sstream> #include <ranges></ranges></sstream>…

コンセプト定義への属性指定

C++

C++20言語仕様では、コンセプト定義に対して属性(attribute)を指定できない。 template <typename T> [[deprecated("concept")]] // NG: ill-formed concept C = /*...*/; // OK: 変数テンプレート template <typename T> [[deprecated("variable")]] T var = /*...*/; // OK: 関数テ</typename></typename>…

クラステンプレート特殊化型判定

C++

プログラミング言語C++において、与えられた型があるクラステンプレートの特殊化(specialization)か否かを判定する方法。下記コードは複素数std::complexの特殊化か否かを判定するメタ関数およびコンセプト実装例。 // C++11/14/17: is_complexメタ関数 #inc…

C++ min/maxアルゴリズムの正しい実装

C++

C++標準ライブラリstd::min, std::maxアルゴリズムの動作仕様についてメモ。 問題:C++ min/maxアルゴリズムを「正しく」実装せよ。 template <typename T> const T& min(const T& a, const T& b) { // どちらのmin実装が正しい? return a < b ? a : b; // #1 return b </typename>…

move in accumulateアルゴリズム

C++

C++20標準ヘッダ<numeric>のstd::accumulateアルゴリズム内部実装では、T型のアキュムレータ変数(acc)への累積操作時にstd::move関数適用(右辺値への変換)が規定される。 // C++20仕様の累積演算(1要素あたり) acc = std::move(acc) + *iterator; // ^^^^^^^^^^^^</numeric>…

どうしてstd::basic_iosは否定演算子(!)オーバーロードを提供するの?

C++

C++標準ライブラリのI/Oストリーム基底クラステンプレートstd::basic_iosが否定演算子!オーバーロードを提供する理由。本記事の内容はStackOverflowで見つけた質問と回答に基づく。答え:歴史的理由標準化前のC++言語仕様では暗黙の型変換に関する仕様が曖昧…

C++コルーチン送出例外のハンドリング戦略

C++

C++20コルーチンからの例外送出ハンドリングに関するメモ。C++コルーチンライブラリの設計者向け。C++コルーチン言語仕様では、コルーチン送出例外ハンドリングのカスタマイズポイントとしてpromise_type::unhandled_exception関数を規定する。プログラマが…

コルーチン×ラムダ式キャプチャ=鼻から悪魔

C++

C++20 コルーチンとキャプチャありラムダ式の組合せは、キャプチャ変数の生存期間(lifetime)切れによる未定義動作(undefined behavior)を引き起こすリスクが高く、原則として併用すべきでない。要約:ラムダ式でキャプチャした変数はコルーチン中断時にコル…

1 << 31 == ?

C++

C++言語における符号付き整数型の左ビットシフト<<と符号ビットの関係について。まとめ: 2の補数表現が保証されたC++20現在、左ビットシフト<<は論理左シフト(logical left shift)が保証される。 おまけ:C++20現在、右ビットシフト>>は算術右シフト(arithm…

Preconditions: false is true.

C++2b(C++23)向けに提案されているコード不到達表明std::unreachable関数の前提条件。 2022-02-09追記:2022年2月会合にて(PDF)P0627R6が採択され、C++2b標準<utility>ヘッダにstd::unreachable関数が追加される。2022-07-25追記:次世代C言語標準でもC2x(C23)向け提</utility>…

2進数フォーマット出力 in 標準C

プログラミング言語Cの次期C2x(C23)標準ライブラリのprintf関数ファミリでは、変換指定子bによる2進数フォーマット出力がサポートされる。同時にscanf関数ファミリやstrtoT関数では0bプレフィクス付き文字列入力がサポートされる。*1 // C2x #include <stdio.h> print</stdio.h>…

自己再帰するラムダ式 @ C++23

次期C++2b(C++23)言語仕様に追加される Deducing this により、自己再帰するラムダ式を自然に記述できるようになる。ラムダ式の第1引数型this autoで宣言されるselfは explicit object parameter と呼ばれ、ここではラムダ式自身のクロージャ型(closure type…

signatureの定義 @ C++20

C++

C++20以降での関数シグネチャ(signature)の定義について。Concepts導入によりテンプレート制約も追加で考慮される。まとめ: 関数:名前、引数型リスト、所属する名前空間(戻り値型は除外) 関数テンプレート:名前、引数型リスト、戻り値型、所属する名前…

std::coutの実体はどこ?

C++標準ライブラリで定義されるグローバルオブジェクトstd::cout等の宣言と定義についてメモ。GCC/libstdc++およびClang/libcxxライブラリ実装では、宣言型(std::ostream)と実体定義の型(char[])を意図的に変えている。型の不一致は厳密にはC++仕様違反*1だ…

レンジ to コンテナ変換

次期C++2b(C++23)標準ライブラリに向けて、Rangesから各種コンテナ型への直接変換サポートが検討されている。(PDF)P1206R6では下記の機能追加/拡張を提案している。 コンテナ型Cへの変換std::ranges::to<C>レンジアダプタ(range adaptor) 標準コンテナへのstd:</c>…

Last Piece of ラムダ式への属性指定

C++20現在の言語仕様では、ラムダ式に対して(普通のプログラマが期待するであろう)属性指定は行えない。C++2b(C++23)に向けた提案(PDF)P2173R0が進行中。 2022-02-17追記:2022年2月会合にてC++2b(C++23)へ提案文書(PDF)P2173R1が採択された。下記コードは…

可変長コンセプト×畳み込み式: The glass is half full or half empty?

C++

C++20コンセプトと論理演算子(&&, ||)による畳み込み式(fold expression)の関係について。本記事の内容はStackOverflowで見つけた質問と回答に基づく。まとめ:&&と||による畳み込み式を用いた制約式(constraint-expression)は機能するものの、コンセプト間…

requires式中でのコンセプト制約表現には要注意

C++20 requires式(requires-expression) において、コンセプトや条件式を用いた制約(constraints)表現には注意が必要。 2022-05-08追記:gcc(g++) 12.1から警告 -Wmissing-requires が追加され、本記事で言及しているrequiresキーワード指定忘れの可能性を検…

HRESULT型からのエラーメッセージ取得

WindowsOS環境のHRESULT型エラーコードからエラーメッセージ文字列へのお手軽変換。Microsoft Visual C++(MSVC)限定。 #include <windows.h> #include <system_error> std::string get_message(HRESULT hr) { return std::system_category().message(hr); } // GetLastError()戻り値な</system_error></windows.h>…

ジュラシック・パーク in C++ Standard

C++

プログラミング言語C++標準規格に潜む恐竜たち。C++20(N4861) D.5 Deprecated volatile typesより引用。*1 1 Postfix ++ and -- expressions (7.6.1.5) and prefix ++ and -- expressions (7.6.2.2) of volatile-qualified arithmetic and pointer types are…

RangeとViewとconst修飾

C++

C++20 RangesライブラリのRangeとViewとconst修飾の関係についてメモ。まとめ: 対象Rangeのconst修飾(要素の変更可否)と、Viewのconst修飾(const-iterableの可否)は異なる概念である。 C++20標準ライブラリ提供の一部Rangeアダプタでは、const修飾によ…

Rangeアダプタ std::view::reverse

C++20 Rangesライブラリの逆順ビューstd::ranges::reverse_viewおよびRangeアダプタstd::views::reverse*1についてメモ。 基本の使い方 範囲for構文とRangeアダプタreverseを組み合わせて、配列や文字列やコンテナなどRangeとして扱えるものを逆順に列挙でき…