yohhoyの日記

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

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)の順にオブジェ…

"Dreams come" == true

PHP

プログラミング言語PHPにおける奇妙な型変換 "Type Juggling"・第2弾。真偽値との比較にも要注意。 Type Juggling規則により「片方がbool型の場合は両辺をbool型として比較評価」する。関連URL Type Juggling - yohhoyの日記 https://twitter.com/ockeghem/…

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

C++

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

{void,value,both}-compatibleラムダ式

プログラミング言語Javaにおけるラムダ式は、その本体部に応じてvoid-compatible/value-compatible/その両方に区分される。void-compatibleラムダ式はRunnableなどの戻り値を持たない(void)関数型インタフェース(functional interface)へ、value-compatibl…

returns_twice属性

GCCとClangの独自拡張 returns_twice 属性についてメモ。対象関数から「2回以上制御が戻ってくる可能性」*1をコンパイラに伝える属性。コンパイラによる一部の最適化処理を抑止する。 The returns_twice attribute tells the compiler that a function may r…

-fimplicit-constexprオプション

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

連番配列を生成

JavaScript(ECMAScript)で連番配列を生成するコード片。いわゆる range 関数に相当。 // NG: [undefined, undefined, undefined, undefined, undefined] // { length: 5 } のみ設定されたArrayオブジェクトが生成される // 各要素は未設定(undefinedとも異…

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…

Math.min@浮動小数点数の実装

Java標準ライブラリMath.minメソッドの実装についてメモ。浮動小数点数型(float, double)に対するminでは、NaN(Not a Number)および負のゼロ(-0.0)を考慮する必要がある。*1 public static double min(double a, double b) { if (a != a) return a; // a is …

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++言語仕様では暗黙の型変換に関する仕様が曖昧…

OpenMP 5.2仕様リリース

2021年11月 OpenMP 5.2仕様リリース記事 OpenMP ARB Releases OpenMP 5.2 with Improvements and Refinements より抄訳。OpenMP仕様バージョン5.2はOpenMP ARB、主要なコンピュータハードウェア/ソフトウェアベンダのグループ、そしてOpenMPコミュニティの…

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> printf(</stdio.h>…

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

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

OpenMP 最長コンストラクト

OpenMPの最長コンストラクト*1 Target Teams Distribute Parallel Worksharing-Loop SIMD Construct。 // OpenMP 4.0 for C/C++ #pragma omp target teams distribute parallel for simd /*for-loops*/ 関連URL OpenMP 4.0仕様リリース - yohhoyの日記 https…

typeof null == 'object'

バグは夜更け過ぎに仕様に変わるだろう*1 -- 詠人知らず // This stands since the beginning of JavaScript typeof null === 'object'; In the first implementation of JavaScript, JavaScript values were represented as a type tag and a value. The ty…

signatureの定義 @ C++20

C++

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

std::coutの実体はどこ?

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