初期のLinuxカーネル(Version 0.12)ソースコード詳細解説と図解を試みる電子書籍。1109ページの超大作。
- http://www.oldlinux.org/
- (PDF) "A Heavily Commented Linux Kernel Source Code," Zhao Jiong
初期のLinuxカーネル(Version 0.12)ソースコード詳細解説と図解を試みる電子書籍。1109ページの超大作。
プログラミング言語C++において、単一メンバしか含まない共用体(union)を用いるとオブジェクトの明示的な生成/破棄操作が可能となる。貧者(poor man's)のOptional。
#include <iostream> template <typename T> union Wrapper { // 共用体のコンストラクタ/デストラクタ定義は必須 Wrapper() {} ~Wrapper() {} // 明示的なオブジェクト初期化 void init() { new (&obj_) Holder; } // 明示的なオブジェクト廃棄 void destroy() { obj_.~Holder(); } // 制御対象クラス struct Holder { T m_; } obj_; }; struct S { S() { std::cout << "S::ctor\n"; } ~S() { std::cout << "S::dtor\n"; } }; int main() { Wrapper<S> opt; // このタイミングではS型オブジェクトは生成されない std::cout << "call init\n"; opt.init(); // S::S()を呼び出し std::cout << "call destroy\n"; opt.destroy(); // S::~S()を呼び出し }
C++17 12.3/p1, 6より一部引用。
1 In a union, a non-static data member is active if its name refers to an object whose lifetime has begun and has not ended (6.8). At most one of the non-static data members of an object of union type can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time. (snip)
6 [Note: In general, one must use explicit destructor calls and placement new-expression to change the active member of a union. -- end note] [Example: Consider an object
u
of aunion
typeU
having non-static data membersm
of typeM
andn
of typeN
. IfM
has a non-trivial destructor andN
has a non-trivial constructor (for instance, if they declare or inherit virtual functions), the active member of u can be safely switched from m to n using the destructor and placement new-expression as follows:u.m.~M(); new (&u.n) N;-- end example]
関連URL
PythonではUnicodeコードポイントによるリテラル表現*1の他に、Unicode文字データベース(UCD; Unicode Character Database)*2に準じた名前表現もサポートする。
print("\U0001F4DB") # 📛 print("\N{NAME BADGE}") # 📛 print("\N{TOFU ON FIRE}") # SyntaxError: # (unicode error) 'unicodeescape' codec can't decode bytes in position 0-15: # unknown Unicode character name
関連URL
Go言語におけるインクリメント++
/デクリメント--
演算子は、後置(postfix)記法のみが許容され、式(expression)ではなく 文(statement) を構成する。
i++; // i += 1; と等価 i--; // i -= 1; と等価
Why are ++ and -- statements and not expressions? And why postfix, not prefix?
https://golang.org/doc/faq
Without pointer arithmetic, the convenience value of pre- and postfix increment operators drops. By removing them from the expression hierarchy altogether, expression syntax is simplified and the messy issues around order of evaluation of++
and--
(considerf(i++)
andp[i] = q[++i]
) are eliminated as well. The simplification is significant. As for postfix vs. prefix, either would work fine but the postfix version is more traditional; insistence on prefix arose with the STL, a library for a language whose name contains, ironically, a postfix increment.
関連URL
Clangコンパイラはユーザ定義のコンパイル警告/エラーメッセージ出力を行うdiagnose_if
属性を提供する。
The
diagnose_if
attribute can be placed on function declarations to emit warnings or errors at compile-time if calls to the attributed function meet certain user-defined criteria. For example:void abs(int a) __attribute__((diagnose_if(a >= 0, "Redundant abs call", "warning"))); void must_abs(int a) __attribute__((diagnose_if(a >= 0, "Redundant abs call", "error"))); int val = abs(1); // warning: Redundant abs call int val2 = must_abs(1); // error: Redundant abs call int val3 = abs(val); int val4 = must_abs(val); // Because run-time checks are not emitted for // diagnose_if attributes, this executes without // issue.https://releases.llvm.org/5.0.0/tools/clang/docs/AttributeReference.html#diagnose-if
C++標準ライブラリlibcxxでは、このdiagnose_if
属性を利用してC++標準ライブラリ要件(requirements)診断を部分的に行っている。
map
,sec
のテンプレートパラメータ最新C17までカバーした、モダンなC言語プログラミングに関する電子書籍。PDF形式(315頁)はCC BY-NC-ND 4.0ライセンス。
C++標準ライブラリが定める InputIterator 要件(requirement) と input_iterator
コンセプト(concept) の変遷についてメモ。
まとめ:
input_iterator
コンセプトではイテレータ型にoperator*
オーバーロードのみ要求する。operator->
オーバーロードは要求されない。operator*
とoperator->
オーバーロードの両方を要求する。Cpp17InputIterator要件はoperator->
オーバーロードを要求するが、input_iterator
コンセプトはoperator->
オーバーロードを要求しない。
C++2aに向けて採択された提案文書(PDF)P0896R4では、[iterator.requirements.general]セクションから下記Wordingが明示的に削除されている。
An iterator
i
for which the expression(*i).m
is well-defined supports the expressioni->m
with the same semantics as(*i).m
.
N4835*1 23.2, 23.3.1/p1, 23.3.4.2/p1-2, 23.3.4.6/p1, 23.3.4.9/p1, 23.3.5.2 Table 83より一部引用。
Header <iterator> synopsis
namespace std { template<class T> using with-reference = T&; // exposition only template<class T> concept can-reference // exposition only = requires { typename with-reference<T>; }; template<class T> concept dereferenceable // exposition only = requires(T& t) { { *t } -> can-reference; // not required to be equality-preserving }; // (snip) }
1 Iterators are a generalization of pointers that allow a C++ program to work with different data structures (for example, containers and ranges) in a uniform manner. To be able to construct template algorithms that work correctly and efficiently on different types of data structures, the library formalizes not just the interfaces but also the semantics and complexity assumptions of iterators. An input iterator
i
supports the expression*i
, resulting in a value of some object typeT
, called the value type of the iterator. (snip)
1 Types that are readable by applying
operator*
model thereadable
concept, including pointers, smart pointers, and iterators.template<class In> concept readable = /*(snip)*/;2 Given a value
i
of typeI
,I
modelsreadable
only if the expression*i
is equality-preserving. [Note: The expression*i
is indirectly required to be valid via the exposition-only dereferenceable concept (23.2). -- end note]
1 The
input_or_output_iterator
concept forms the basis of the iterator concept taxonomy; every iterator modelsinput_or_output_iterator
. This concept specifies operations for dereferencing and incrementing an iterator. Most algorithms will require additional operations to compare iterators with sentinels (23.3.4.7), to read (23.3.4.9) or write (23.3.4.10) values, or to provide a richer set of iterator movements (23.3.4.11, 23.3.4.12, 23.3.4.13).template<class I> concept input_or_output_iterator = requires(I i) { { *i } -> can-reference; } && weakly_incrementable<I>;
1 The
input_iterator
concept defines requirements for a type whose referenced values can be read (from the requirement forreadable
(23.3.4.2)) and which can be both pre- and post-incremented. [Note: Unlike the Cpp17InputIterator requirements (23.3.5.2), theinput_iterator
concept does not need equality comparison since iterators are typically compared to sentinels. -- end note]template<class I> concept input_iterator = input_or_output_iterator<I> && readable<I> && requires { typename ITER_CONCEPT(I); } && derived_from<ITER_CONCEPT(I), input_iterator_tag>;
Table 83: Cpp17InputIterator requirements (in addition to Cpp17Iterator)
- Expression
a->m
- Operational semantics
(*a).m
- Assertion/note pre-/post-condition
- Expects:
a
is dereferenceable.
Input iterator要件はoperator->
オーバーロードを要求する。 C++17 27.2.3 Table 95より該当箇所を引用。
- Expression
a->m
- Operational semantics
(*a).m
- Assertion/note pre-/post-condition
- Requires:
a
is dereferenceable.
C++17以降、LWG DR 2790にて istreambuf_iterator::operator->
は削除された。
Input iterator要件はoperator->
オーバーロードを要求する。 C++11 24.2.3 Table 107より該当箇所を引用。C++14でも同一。
- Expression
a->m
- Operational semantics
(*a).m
- Assertion/note pre-/post-condition
- pre:
a
is dereferenceable.
C++11以降、LWG DR 659にて istreambuf_iterator::operator->
が追加された。