将类型更改为类型reference,允许访问类型的成员而不创建类型的实例.对于两者而言lvalue references,这似乎都是正确的rvalue references.
declval是用add_rvalue_reference 而不是 add_lvalue_reference,
add_rvalue_reference?编辑:我想我有点模糊,这些答案都非常好,但触及略有不同的点.建议使用两种不同的答案,Howard强调您可以选择您的类型具有哪种参考,使其add_rvalue_reference更加灵活.其他答案强调默认行为会自动选择更自然地反映输入类型的引用.我不知道该挑选什么!如果有人可以添加两个简单的例子,分别激励每个属性的需要,那么我会满意的.
gx_*_*gx_ 32
用add_rvalue_reference:
declval<Foo>()是类型的Foo&&. declval<Foo&>()是类型Foo&(参考折叠:" Foo& &&"折叠到Foo&).declval<Foo&&>()是类型Foo&&(参考折叠:" Foo&& &&"折叠到Foo&&).用add_lvalue_reference:
declval<Foo>()将是类型Foo&. declval<Foo&>()将是类型Foo&(参考折叠:" Foo& &"折叠到Foo&).declval<Foo&&>()将是类型Foo& (!)(参考折叠:" Foo&& &"折叠到Foo&).也就是说,你永远不会得到一个Foo&&.
此外,declval<Foo>()类型的事实Foo&&很好(你可以写Foo&& rr = Foo();但不能Foo& lr = Foo();).这种类型只是感觉"错"!declval<Foo&&>()Foo&
编辑:因为你问了一个例子:
#include <utility>
using namespace std;
struct A {};
struct B {};
struct C {};
class Foo {
public:
Foo(int) { } // (not default-constructible)
A onLvalue() & { return A{}; }
B onRvalue() && { return B{}; }
C onWhatever() { return C{}; }
};
decltype( declval<Foo& >().onLvalue() ) a;
decltype( declval<Foo&&>().onRvalue() ) b;
decltype( declval<Foo >().onWhatever() ) c;
Run Code Online (Sandbox Code Playgroud)
如果declval使用add_lvalue_reference你就不能使用onRvalue()它(第二个decltype).
是的,使用add_rvalue_reference赋予客户端选择指定他是否需要给定类型的左值或右值对象:
#include <type_traits>
#include <typeinfo>
#include <iostream>
#ifndef _MSC_VER
# include <cxxabi.h>
#endif
#include <memory>
#include <string>
#include <cstdlib>
template <typename T>
std::string
type_name()
{
typedef typename std::remove_reference<T>::type TR;
std::unique_ptr<char, void(*)(void*)> own
(
#ifndef _MSC_VER
abi::__cxa_demangle(typeid(TR).name(), nullptr,
nullptr, nullptr),
#else
nullptr,
#endif
std::free
);
std::string r = own != nullptr ? own.get() : typeid(TR).name();
if (std::is_const<TR>::value)
r += " const";
if (std::is_volatile<TR>::value)
r += " volatile";
if (std::is_lvalue_reference<T>::value)
r += "&";
else if (std::is_rvalue_reference<T>::value)
r += "&&";
return r;
}
int
main()
{
std::cout << type_name<decltype(std::declval<int>())>() << '\n';
std::cout << type_name<decltype(std::declval<int&>())>() << '\n';
}
Run Code Online (Sandbox Code Playgroud)
哪个对我输出:
int&&
int&
Run Code Online (Sandbox Code Playgroud)
您希望能够取回 a T、 aT&或const/volatile限定版本。由于可能没有复制或移动构造函数,因此不能只返回类型,即需要返回引用。另一方面,向引用类型添加右值引用没有任何效果;
std::declval<T> -> T&&
std::declval<T&> -> T&
Run Code Online (Sandbox Code Playgroud)
也就是说,添加右值引用类型会产生看起来像传递类型的对象的结果!