web-dev-qa-db-ja.com

std :: declvalが参照を追加するのはなぜですか?

_std::declval_ は、型を判別する目的で式を作成するために使用されるコンパイル時ユーティリティです。これは次のように定義されます。

_template< class T >
typename std::add_rvalue_reference<T>::type declval() noexcept;
_

代わりにこれは簡単ではないでしょうか?

_template< class T >
T declval() noexcept;
_

参照戻り値の型の利点は何ですか?そして、それはdeclrefと呼ばれるべきではありませんか?

私が見つけた最も初期の歴史的な例は n2958 で、これは関数value()を呼び出しますが、すでに常に参照を返します。

decltypeのオペランドは、アクセス可能なデストラクタを持っている必要はありません。つまり、完全な式として意味的にチェックされないことに注意してください。

_template< typename t >
t declprval() noexcept;

class c { ~ c (); };
decltype ( declprval< c >() ) * p = nullptr; // OK
_
43
Potatoswatter

decltypeのオブジェクトタイプのprvalueを返す関数に一時的なものは導入されません」ルールは、関数呼び出し自体がdecltypeのオペランド、またはdecltypeのオペランドであるコンマ演算子の右オペランドのいずれかである場合にのみ適用されます(§5.2.2[expr .call]/p11)、これは、OPでdeclprvalが指定されていることを意味します。

template< typename t >
t declprval() noexcept;

class c { ~ c (); };

int f(c &&);

decltype(f(declprval<c>())) i;  // error: inaccessible destructor

コンパイルされません。より一般的には、Tを返すことで、不完全な型、プライベートデストラクタを使用した型などでのdeclvalのほとんどの重要な使用を防ぐことができます。

class D;

int f(D &&);

decltype(f(declprval<D>())) i2;  // doesn't compile. D must be a complete type

xvaluesはdecltypeを使用する場合を除いて、prvaluesとほとんど区別がつかず、通常はdecltypeの戻り値に直接declvalを使用しないため、これを行うことにはほとんどメリットがありません。タイプはすでにわかっています。

37
T.C.

配列を値で返すことはできないため、値で配列を返す関数の宣言だけでも無効なコードです。

ただし、参照によって配列を返すことができます。

12
6502

decltype()の目的は、タイプTの有効な値として機能する式を作成し、Tsを期待する式にTとして配置することです。 。問題は、C++では、タイプTがコピー不可能であるか、デフォルトで構築できない可能性があることです。したがって、その目的で_T{}_を使用することは機能しません。

decltype()が行うことは、右辺値参照をTに返すことです。右辺値参照はすべてのタイプTに対して有効である必要があるため、Tの右辺値参照から有効なTがあることが保証され、右辺値を持つことができることが保証されます任意のタイプへの参照T。それがトリックです。

decltype()を "T"型の有効な式を教えてください。もちろん、その使用法は、過負荷の解決、タイプの決定などを目的としています。その目的は有効な式(構文上の意味で)を返すことであり、値を返すことではないためです。これは、std::declval()がまったく定義されておらず、宣言されているだけであるという事実に反映されています。
それが定義された場合、最初の問題が再び発生します(任意の型Tの値を作成する必要があり、それは不可能です)。

4
Manu343726