yohhoyの日記

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

DECAY_COPY

C++11標準ライブラリのスレッドサポートライブラリ定義で用いられるDECAY_COPY関数に関するメモ*1

2021-10-21追記:C++2b(C++23)に向けた提案文書 P0849R8 が採択され、decay-copy動作を行う明示型変換(explicit type conversion)式auto(t), auto{t}が言語仕様に追加される。

大雑把に、DECAY_COPY(t)の結果はauto x = t;と代入した変数xに相当する*2

  • tが型Tのrvalueの場合はxはムーブされた型Tオブジェクト。それ以外ならxはコピーされた型Tオブジェクトとなる。
  • tが配列型の場合、xは先頭要素へのポインタとなる。(4.2 Array-to-pointer conversion相当)
  • tが関数型の場合、xは関数へのポインタとなる。(4.3 Function-to-pointer conversion相当)

DECAY_COPYは下記の Effects 定義において、INVOKE( DECAY_COPY(std::forward<F>(f)), DECAY_COPY(std::forward<Args>(args))...)のように利用されている。動作イメージとしては「ファンクタfに、コピー/ムーブした実引数群arg...を指定して呼び出す」となる*3。このため、引数を参照として渡す場合はstd::refを利用する必要がある。

// threadコンストラクタ(30.3.1.2)
template <class F, class ...Args>
  explicit thread(F&& f, Args&&... args);
// call_once関数(30.4.4.2)
template<class Callable, class ...Args>
  void call_once(once_flag& flag, Callable&& func, Args&&... args);
// async関数(30.6.8)
template <class F, class... Args>
  future<〜> async(F&& f, Args&&... args);
template <class F, class... Args>
  future<〜> async(launch policy, F&& f, Args&&... args);

N3337 30.2.6/p1より引用。

In several places in this Clause the operation DECAY_COPY(x) is used. All such uses mean call the function decay_copy(x) and use the result, where decay_copy is defined as follows:

template <class T> typename decay<T>::type decay_copy(T&& v)
  { return std::forward<T>(v); }

関連URL

*1:DECAY_COPY はライブラリユーザへ提供される関数ではなく、§30 Thread support library の動作定義でのみ利用される。

*2:より厳密な動作は std::decay<T> の定義を参照のこと。

*3:型 F や Args 中の全ての型 Ti は、MoveConstructible 要件を満たさなければならない。(30.3.1.2/p3, 30.4.4.2/p1, 30.6.8/p2)