式がC++の右辺値または左辺値であるかどうかを判断する最良の方法は何ですか?おそらく、これは実際には有用ではありませんが、右辺値と左辺値を学習しているので、関数is_lvalue
は、入力で渡された式が左辺値である場合はtrueを返し、そうでない場合はfalseを返します。
例:
std::string a("Hello");
is_lvalue(std::string()); // false
is_lvalue(a); // true
ほとんどの作業はすでにstdlibによって行われています。関数ラッパーが必要です。
template <typename T>
constexpr bool is_lvalue(T&&) {
return std::is_lvalue_reference<T>{};
}
std::string
lvalueを渡す場合、T
はstd::string&
またはconst std::string&
に推定され、右辺値の場合はstd::string
に推定されます
Yakk's answer は異なる型を返すことに注意してください。これにより柔軟性が増し、その答えを読んで、おそらく代わりに使用する必要があります。
2つのオーバーロードされたテンプレート関数を使用して、上記の質問を解決しました。最初は、入力として左辺値への参照を取り、true
を返します。一方、2番目の関数は右辺値への参照を使用します。次に、入力として渡された式に応じて、コンパイラに正しい関数を一致させます。
コード:
#include <iostream>
template <typename T>
constexpr bool is_lvalue(T&) {
return true;
}
template <typename T>
constexpr bool is_lvalue(T&&) {
return false;
}
int main()
{
std::string a = std::string("Hello");
std::cout << "Is lValue ? " << '\n';
std::cout << "std::string() : " << is_lvalue(std::string()) << '\n';
std::cout << "a : " << is_lvalue(a) << '\n';
std::cout << "a+b : " << is_lvalue(a+ std::string(" world!!! ")) << '\n';
}
出力:
Is Lvalue ?
std::string() : 0
a : 1
a+b : 0
boost::hana
からページを取得し、is_lvalue
の戻り値にその引数の左辺値をエンコードさせますbothとしてconstexpr
値、- andタイプとして。
これにより、余分なボイラープレートなしでタグのディスパッチなどを行うことができます。
template<class T>
constexpr std::is_lvalue_reference<T&&>
is_lvalue(T&&){return {};}
この関数の本体は何もせず、パラメーターの値は無視されます。これにより、constexpr以外の値でもconstexprになります。
この手法の利点は次のとおりです。
void tag_dispatch( std::true_type ) {
std::cout << "true_type!\n";
}
void tag_dispatch( std::false_type ) {
std::cout << "not true, not true, shame on you\n";
}
tag_dispatch( is_lvalue( 3 ) );
is_lvalue
の戻り値がconstexpr
コンテキストで利用できるだけでなく(true_type
およびfalse_type
にはconstexpr operator bool
があるため)、簡単に選択できますその状態に基づいて過負荷。
もう1つの利点は、コンパイラが結果をnotインライン化するのを難しくすることです。 constexpr
値を使用すると、コンパイラはそれが真の定数であることを「簡単に」忘れることができます。型がある場合、忘れられる可能性があるため、最初にbool
に変換する必要があります。
使用する - std::is_lvalue_reference
および std::is_rvalue_reference
。
Decltypeの使用に満足している場合は、ラッパーは必要ありません。
std::string a("Hello");
std::is_lvalue_reference<decltype((std::string()))>::value; // false
std::is_lvalue_reference<decltype((a))>::value; // true
C++ 17では、次のものを使用できます。
std::string a("Hello");
std::is_lvalue_reference_v<decltype((std::string()))>; // false
std::is_lvalue_reference_v<decltype((a))>; // true
または、@ Ryan Hainingが提案するようにラッパーを書くこともできます。タイプが正しいことを確認してください。