yohhoyの日記

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

#elifdefと#elifndef

プログラミング言語C/C++のそれぞれ次期バージョンC2x(C23)/C++2b(C++23)では、新しいプリプロセッサディレクティブ#elifdef#elifndefが追加される予定。*1

  • #ifdef identifier#if defined(identifier)と等価
  • #ifndef identifier#if !defined(identifier)と等価
  • #elifdef identifier#elif defined(identifier)と等価
  • #elifndef identifier#elif !defined(identifier)と等価

おまけ:本提案に対する反応の一つ。

"if I had a time machine, I’d blow #ifdef up and just make people used #if defined(...), it’s better and more flexible and represents the same functionality";

No Us Without You - elifdef and elifndef | The Pasture

関連URL

*1:2021年6月現在、次期C言語C2xには採択済み。次期C++言語C++2bへの追加はまだ提案段階。 2021年9月投票にてC++2b採択が決定した。

James Bond in C++ Standard

プログラミング言語C++標準規格の索引(Index)に紛れ込むジェームズ・ボンド

[expr.prim.lambda] Add index entry for example of *this capture.

https://github.com/cplusplus/draft/commit/703d892264af814a64140b17ffe2bf6ae9274dde

関連URL

OpenMP 5.1仕様リリース

2020年11月 OpenMP 5.1仕様リリース記事 OpenMP ARB releases OpenMP 5.1 with Vital Usability Enhancements より抄訳。

OpenMP仕様バージョン5.1はOpenMP ARB、主要なコンピュータハードウェア/ソフトウェアベンダのグループ、そしてOpenMPコミュニティのユーザによって共同開発されました。改訂仕様は下記の主要な機能追加を含みます:

アクセラレータデバイス相互作用の改善:

コンパイラ最適化の改善を可能とする多くの情報提供:

  • assumeディレクティブによってプログラムのOpenMP利用方法に関する追加情報を処理系へと指示でき、コンパイラによって安全に適用できる追加の最適化や、安全なOpenMPサブセット実装が可能となります。*2
  • データ局所性を向上させるtileディレクティブから始まり、ループを完全または部分的に展開するunrollディレクティブと、ループ変形ディレクティブが追加されます。

スレッド実行のフィルタリング:

  • maskedディレクティブによりコード区間の実行をスレッド・サブセットに制限できます。

ユーザによるコンパイル時エラー・警告生成の許可:

  • 新しいerrorディレクティブが追加されます。

モダンC++におけるOpenMP利用の改善:

  • 旧来のpragma形式に代わって、OpenMPディレクティブ指定にC++属性構文を利用できるようになり、テンプレートとの統合がシンプルになります。*3
  • C11, C18, C++11, C++14, C++17, C++20のフルサポート:これらの言語で書かれたプログラムはOpenMP並列化可能です。

Fortranサポートの改善:

  • Fortran 2008が完全にポートされ、Fortran 2018への初期サポートが追加されます。

環境固有な関数宣言の簡易化:

  • 単一declare variantコンストラクトに複数関数を宣言可能となり、コードを特定環境により一層合わせられます。

関連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`)...

制約式std::bool_constant<cond>::value

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 type G 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 which g'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

2進数リテラル in 標準C

プログラミング言語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

std::is_convertible vs. std::convertible_to

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 and To and an expression E such that decltype((E)) is add_rvalue_reference_t<From>, convertible_to<From, To> requires E to be both implicitly and explicitly convertible to type To. 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 and From. 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