タイトル通り。ISO/IEC JTC1/SC22/WG14サイト各種文書への短縮リンク提供サービス。
2024-01-04追記:ドメイン失効(?)によるリンク切れを確認。
wg14.link/nXXXX
Get document.wg14.link/{c99,c11,c18,c2x}
https://wg14.link/
Get latest working draft.
関連URL
タイトル通り。ISO/IEC JTC1/SC22/WG14サイト各種文書への短縮リンク提供サービス。
2024-01-04追記:ドメイン失効(?)によるリンク切れを確認。
wg14.link/nXXXX
Get document.wg14.link/{c99,c11,c18,c2x}
https://wg14.link/
Get latest working draft.
関連URL
2020年11月 OpenMP 5.1仕様リリース記事 OpenMP ARB releases OpenMP 5.1 with Vital Usability Enhancements より抄訳。
OpenMP仕様バージョン5.1はOpenMP ARB、主要なコンピュータハードウェア/ソフトウェアベンダのグループ、そしてOpenMPコミュニティのユーザによって共同開発されました。改訂仕様は下記の主要な機能追加を含みます:
コンパイラ最適化の改善を可能とする多くの情報提供:
スレッド実行のフィルタリング:
ユーザによるコンパイル時エラー・警告生成の許可:
Fortranサポートの改善:
環境固有な関数宣言の簡易化:
関連URL
*1: (PDF)Additional Definitions (v2.0)によれば次の外部ランタイム環境が定義される:NVIDIA CUDA, Khronos OpenCL, Khronos SYCL, AMD ROCm HIP, Intel oneAPI Level Zero
*2:訳注:“対象コード区間は入れ子OpenMPディレクティブを含まない” といった最適化ヒント情報を表明できる。
*3:訳注:名前空間 omp 以下に directive と sequence の2属性が追加される。for構文に omp parallel と omp for ディレクティブを指定する例:[[omp::sequence( directive(parallel), directive(for) )]] for (/*...*/) {} 積極的に使いたくなる構文ではない('A`)...
C++20 制約式(constraint-expression)でテンプレートパラメータに依存する定数条件式cond
を表現する場合、非定数式に起因するハードエラーを防ぐためstd::bool_constant<cond>::value
と記述する必要がある。
#include <type_traits> struct X { // X::valueは非定数式 static inline int value = 42; }; struct Y { // Y::valueは定数式 static constexpr inline int value = 42; }; struct Z {}; template<typename T> concept C0 = (T::value == 42); static_assert(!C0<X>); // NG: ill-formed static_assert( C0<Y>); // OK static_assert(!C0<Z>); // OK template<typename T> concept C1 = std::bool_constant<T::value == 42>::value; static_assert(!C1<X>); // OK static_assert( C1<Y>); // OK static_assert(!C1<Z>); // OK
C++標準ライブラリではuniform_random_bit_generator
コンセプトで同テクニックが利用される。C++20 26.6.2.3/p1より引用。
A uniform random bit generator
g
of typeG
is a function object returning unsigned integer values such that each value in the range of possible results has (ideally) equal probability of being returned. [Note: The degree to whichg
's results approximate the ideal is often determined statistically. --end note]template<class G> concept uniform_random_bit_generator = invocable<G&> && unsigned_integral<invoke_result_t<G&>> && requires { { G::min() } -> same_as<invoke_result_t<G&>>; { G::max() } -> same_as<invoke_result_t<G&>>; requires bool_constant<(G::min() < G::max())>::value; };
関連URL
プログラミング言語Cの次期仕様C2x(C23)では 2進数リテラル(binary literal) が正式仕様となる。そこ今更とか言わない。
// C2x unsigned x = 0b101010; unsigned y = 0B11110000;
ノート:2003年時点の (PDF) Rationale for International Standard Programming Languages Cでは下記の通り否定的だったが、C++14で2進数リテラルが導入されたことも影響していそう。
6.4.4.1 Integer constants
A proposal to add binary constants was rejected due to lack of precedent and insufficient utility.
関連URL
C++標準ライブラリstd::is_convertible
メタ関数とstd::convertible_to
コンセプトの超微妙な違い。本記事の内容はStackOverflowで見つけた質問と回答に基づく。
要約:
is_convertible<From, To>
メタ関数:From
型からTo
型へ暗黙変換できることを検査する。convertible_to<From, To>
コンセプト:From
型からTo
型へ暗黙変換および明示変換できることを検査する。暗黙変換は可能だが明示変換が許可されないケースで差異が生じる。ジェネリックライブラリの設計者大変すぎでしょ。
#include <concepts> #include <type_traits> struct From; struct To { To() = default; // From→Toの明示変換を禁止 explicit To(From) = delete; }; struct From { // From→Toの暗黙変換は許可 operator To() { return {}; } }; static_assert( std::is_convertible_v<From, To> ); static_assert( !std::convertible_to<From, To> ); To to1 = From{}; // OK: 暗黙変換 To to2{From{}}; // NG: 明示変換
C++20(N4861) 18.4.4/p1, 20.15.6/p5より引用(下線部は強調)。
Given types
From
andTo
and an expressionE
such thatdecltype((E))
isadd_rvalue_reference_t<From>
,convertible_to<From, To>
requiresE
to be both implicitly and explicitly convertible to typeTo
. The implicit and explicit conversions are required to produce equal results.template<class From, class To> concept convertible_to = is_convertible_v<From, To> && requires(add_rvalue_reference_t<From> (&f)()) { static_cast<To>(f()); };
The predicate condition for a template specialization
is_convertible<From, To>
shall be satisfied if and only if the return expression in the following code would be well-formed, including any implicit conversions to the return type of the function:To test() { return declval<From>(); }
[Note: This requirement gives well-defined results for reference types, void types, array types, and function types. -- end note] Access checking is performed in a context unrelated to
To
andFrom
. Only the validity of the immediate context of the expression of the return statement (8.7.3) (including initialization of the returned object or reference) is considered. [Note: The initialization can result in side effects such as the instantiation of class template specializations and function template specializations, the generation of implicitly-defined functions, and so on. Such side effects are not in the "immediate context" and can result in the program being ill-formed. -- end note]
関連URL
C++20 requires式(requires-expression)の単純な利用では非static/staticメンバを区別できない。requires式の本体部は評価されない(unevaluated)ため、通常コードとは異なる規則が適用されることに注意。
// staticメンバmを持つ型X struct X { static const int m = 1; }; // (非static)メンバmを持つ型Y struct Y { int m = 2; }; // staticメンバT::mを確認するコンセプト(?) template <typename T> concept HasStaticM = requires { { T::m } -> std::convertible_to<int>; }; // 式 T::m はmがstaticメンバのときのみ有効 assert( X::m == 1 ); // OK static_assert( HasStaticM<X> ); // OK // mが非staticメンバの場合は式 T::m と書けないが... assert( Y::m == 2 ); // NG: ill-formed static_assert( HasStaticM<Y> ); // OK !?
T::m
が非static/staticデータメンバのいずれかを判定するには、&T::m
の型をstd::is_member_object_pointer
メタ関数に通す。
X::m
はstaticデータメンバのため、式&X::m
は通常のポインタ型(int*
)となる。Y::m
は非staticデータメンバのため、式&Y::m
はデータメンバへのポインタ型(int X::*
)となる。template <typename T> concept HasStaticM = requires { { T::m } -> std::convertible_to<int>; requires !std::is_member_object_pointer_v<decltype(&T::m)>; }; static_assert( HasStaticM<X> ); // OK static_assert( !HasStaticM<Y> ); // OK
C++20(N4861) 7.5.4/p2, 7.5.7/p2より引用(下線部は強調)。
id-expression:
unqualified-id
qualified-id
2 An id-expression that denotes a non-static data member or non-static member function of a class can only be used:
- as part of a class member access (7.6.1.4) in which the object expression refers to the member's class or a class derived from that class, or
- to form a pointer to member (7.6.2.1), or
- if that id-expression denotes a non-static data member and it appears in an unevaluated operand. [Example:
struct S { int m; }; int i = sizeof(S::m); // OK int j = sizeof(S::m + 42); // OK-- end example]
2 A requires-expression is a prvalue of type
bool
whose value is described below. Expressions appearing within a requirement-body are unevaluated operands (7.2).
関連URL
C++20標準ライブラリで導入された Customization Point Object (CPO)定義で必要となる Poison-pill*1 オーバーロードについてメモ。std::ranges::swap
やstd::ranges::begin/end
などのCPO定義で利用される。
本記事の内容はStackOverflowで見つけた質問と回答に基づく。
std::ranges
名前空間でのCPO定義位置からは、親名前空間std
で定義されるカスタマイズポイント同名の制約のない関数テンプレート(std::swap
やstd::begin/end
)が "見えて” しまうため、同関数テンプレートシグネチャをdelete宣言してオーバーロード候補から除外する(★印)。
swap
*2とiter_swap
を除く)CPO実装において Poison-pill オーバーロード が調整される。詳細は [C++]WG21月次提案文書を眺める(2022年06月) - 地面を見下ろす少年の足蹴にされる私 を参照。// std::ranges::swap CPO実装イメージ(超簡略化版) namespace std::ranges { namespace swap_impl { template<class T> void swap(T&, T&) = delete; // ★ struct swap_fn { template<class T1, class T2> requires /* C++20 18.4.9/p2/b1 */ constexpr void operator()(T1& e1, T2& e2) const { // 非修飾名・ADL経由でカスタマイズポイント(swap)を呼び出す swap(e1, e2); } // ... }; } // std::ranges::swap CPO定義 inline namespace swap_cpo { inline constexpr swap_impl::swap_fn swap{}; // Hidden friendとの名前衝突回避のためインライン名前空間が必要 // 詳細説明は提案文書 P1895R0 を参照のこと } }
C++20 Rangesライブラリの前身、Ranges TS検討当時の提案文書 P0370R3 Ranges TS Design Updates Omnibus より一部引用。
unqualified name lookup for the name
swap
could find the unconstrainedswap
in namespacestd
either directly - it’s only a couple of hops up the namespace hierarchy - or via ADL ifstd
is an associated namespace ofT
orU
. Ifstd::swap
is unconstrained, the concept is "satisfied" for all types, and effectively useless. The Ranges TS deals with this problem by requiring changes tostd::swap
, a practice which has historically been forbidden for TSs. Applying similar constraints to all of the customization points defined in the TS by modifying the definitions in namespacestd
is an unsatisfactory solution, if not an altogether untenable.
We propose a combination of the approach used in N4381 with a "poison pill" technique to correct the lookup problem. Namely, we specify that unqualified lookup intended to find user-defined overloads via ADL must be performed in a context that includes a deleted overload matching the signature of the implementation in namespace
std
. E.g., for the customization pointbegin
, the unqualified lookup forbegin(E)
(for some arbitrary expressionE
) is performed in a context that includes the declarationvoid begin(const auto&) = delete;
. This "poison pill" has two distinct effects on overload resolution. First, the poison pill hides the declaration in namespacestd
from normal unqualified lookup, simply by having the same name. Second, for actual argument expressions for which the overload in namespacestd
is viable and found by ADL, the poison pill will also be viable causing overload resolution to fail due to ambiguity. The net effect is to preclude the overload in namespacestd
from being chosen by overload resolution, or indeed any overload found by ADL that is not more specialized or more constrained than the poison pill.
C++20(N4861) 16.4.2.2.6/p6より引用(下線部は強調)。
[Note: Many of the customization point objects in the library evaluate function call expressions with an unqualified name which results in a call to a program-defined function found by argument dependent name lookup (6.5.2). To preclude such an expression resulting in a call to unconstrained functions with the same name in namespace
std
, customization point objects specify that lookup for these expressions is performed in a context that includes deleted overloads matching the signatures of overloads defined in namespacestd
. When the deleted overloads are viable, program-defined overloads need be more specialized (13.7.6.2) or more constrained (13.5.4) to be used by a customization point object. -- end note]
関連URL