C++1zでは、クラステンプレートのテンプレート引数が推論されるようになります。
例として、冗長なコードになりがちなstd::lock_guard
クラスを使用した以下のコードは、
std::mutex m1;
void f()
{
std::lock_guard<std::mutex> lk(m);
}
C++1zでは以下のようにstd::lock_guard
クラスのテンプレート引数を省略して書けるようになります:
std::mutex m;
void f()
{
std::lock_guard lk(m);
}
この場合、m
の型からstd::lock_guard
クラスのテンプレート引数の型が推論されます。
C++1zでは、コンストラクタの引数からクラステンプレートのテンプレート引数が推論されます。std::lock_guard
クラスの場合、先程のコンストラクタは以下のような宣言になっています:
template <class Mutex>
class lock_guard {
public:
typedef Mutex mutex_type;
explicit lock_guard(mutex_type& m);
};
このコンストラクタでは、その引数の型がそのままクラステンプレートのテンプレート引数になっているため、推論ができるようになっています。
ですが、変換コンストラクタのように、コンストラクタの引数から直接クラステンプレートのテンプレート引数を推論できない場合があります。イテレータ範囲を受け取るvector
のコンストラクタを考えます:
namespace std {
template <class T>
class vector {
public:
template <class InputIter>
vector(InputIter first, InputIter last);
};
}
この場合は、引数の型InputIter
からT
を直接推論することはできません。このような場合には、ライブラリ側で推論の補助をする必要があります。推論補助は、クラステンプレートと同じスコープ (クラスの外)に、後置戻り値型 (trailing return type)と同じ構文で、コンストラクタに戻り値の型を明示します:
namespace std {
template <class T>
class vector {
public:
template <class InputIter>
vector(InputIter first, InputIter last);
};
template <class InputIter>
vector(InputIter first, InputIter last)
-> vector<typename iterator_traits<InputIter>::value_type>;
}
これでイテレータ範囲を受け取るvector
のコンストラクタでもクラステンプレートのテンプレート引数が推論できるようになり、以下のように書けるようになります:
std::list ls = {1, 2, 3};
std::vector v(ls.begin(), ls.end());
C++1z時点では、言語側の対応が入るのみで、標準ライブラリではクラステンプレートのテンプレート引数推論のための補助が入る予定はありません。
参照
お断り
この記事の内容は、C++1zが正式リリースされる際には変更される可能性があります。正式リリース後には、C++日本語リファレンスサイトcpprefjpの以下の階層の下に解説ページを用意する予定です。
- 2016/10/25 12:47 : コメント欄でのk_satodaさんの指摘を受け、クラス内のコンストラクタに対して推論補助を記載していたところを、クラス外で推論補助するよう修正