decltype(auto)的一些用途是什么?
What are some uses of decltype(auto)?
在c++14中引入了decltype(auto)
习语。
通常用于允许auto
声明在给定表达式上使用decltype
规则。
搜索"好"使用习惯用法的例子,我只能想到如下(Scott Meyers),即对于,函数的返回类型演绎:
template<typename ContainerType, typename IndexType> // C++14
decltype(auto) grab(ContainerType&& container, IndexType&& index)
{
authenticateUser();
return std::forward<ContainerType>(container)[std::forward<IndexType>(index)];
}
还有其他的例子说明这个新的语言特性是有用的吗?
泛型代码中的返回类型转发
对于非泛型代码,如您给出的初始示例,您可以手动选择获取引用作为返回类型:
auto const& Example(int const& i)
{
return i;
}
但是在泛型代码中,您希望能够完美地转发返回类型,而不知道您是在处理引用还是值。decltype(auto)
赋予你这种能力:
template<class Fun, class... Args>
decltype(auto) Example(Fun fun, Args&&... args)
{
return fun(std::forward<Args>(args)...);
}
延迟递归模板的返回类型扣除
在几天前的这个Q&A中,当模板的返回类型被指定为decltype(iter(Int<i-1>{}))
而不是decltype(auto)
时,在模板实例化期间遇到了无限递归。
template<int i>
struct Int {};
constexpr auto iter(Int<0>) -> Int<0>;
template<int i>
constexpr auto iter(Int<i>) -> decltype(auto)
{ return iter(Int<i-1>{}); }
int main() { decltype(iter(Int<10>{})) a; }
decltype(auto)
在这里用于延迟模板实例化尘埃落定后的返回类型演绎。
您也可以在其他上下文中使用decltype(auto)
,例如,标准草案N3936也规定
7.1.6.4汽车说明符(dcl.spec.auto)
1
占位符类型可以在decl- specific -seq、type- specific -seq、convert -function-id,或尾随返回类型,在任何这样的声明符有效的上下文中。如果函数声明器包含一个尾随返回类型(8.3.5),它指定了函数声明的返回类型。如果函数声明的返回类型包含占位符类型,则函数的返回类型为从函数体中的return语句推导而来,如果有的话。auto
和decltype(auto)
类型说明符指定一个占位符类型,稍后将通过从初始化式或通过带有尾随返回类型的显式规范。auto
类型说明符还用于表示lambda是a通用的λ。
草案还包含了这个变量初始化的例子:
int i;
int&& f();
auto x3a = i; // decltype(x3a) is int
decltype(auto) x3d = i; // decltype(x3d) is int
auto x4a = (i); // decltype(x4a) is int
decltype(auto) x4d = (i); // decltype(x4d) is int&
auto x5a = f(); // decltype(x5a) is int
decltype(auto) x5d = f(); // decltype(x5d) is int&&
auto x6a = { 1, 2 }; // decltype(x6a) is std::initializer_list<int>
decltype(auto) x6d = { 1, 2 }; // error, { 1, 2 } is not an expression
auto *x7a = &i; // decltype(x7a) is int*
decltype(auto)*x7d = &i; // error, declared type is not plain decltype(auto)
引用这里的内容:
-
decltype(auto)
主要用于推断转发函数的返回类型和类似的包装器,其中您希望该类型准确地"跟踪"您正在调用的某些表达式。 -
例如,给定如下函数:
string lookup1();
string& lookup2();
- 在c++ 11中,我们可以编写以下包装器函数,这些函数记住保留返回类型的引用性:
string look_up_a_string_1() { return lookup1(); }
string& look_up_a_string_2() { return lookup2(); }
- 在c++ 14中,我们可以自动执行:
decltype(auto) look_up_a_string_1() { return lookup1(); }
decltype(auto) look_up_a_string_2() { return lookup2(); }
然而,
decltype(auto)
并不打算成为一个广泛使用的功能。 特别是,尽管它可以用于声明局部变量,但这样做可能只是一个反模式,因为局部变量的引用不应该依赖于初始化表达式。
此外,它对您如何编写返回语句很敏感。
例如,下面两个函数有不同的返回类型:
decltype(auto) look_up_a_string_1() { auto str = lookup1(); return str; }
decltype(auto) look_up_a_string_2() { auto str = lookup2(); return(str); }
- 第一个返回
string
,第二个返回string&
,这是对局部变量str
的引用。
从提案中你可以看到更多的预期用途
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- C++避免重复声明的语法是什么
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- C++从另一个类访问公共静态向量的正确方法是什么
- "throw expression code" 1e7 >返回 d 是什么?投掷标准::overflow_error( "too big" ) : d;意味 着?
- C++中名称篡改的目的是什么
- 在 c++ 中拥有一组结构的正确方法是什么?
- 这个指针和内存代码打印是什么?我不知道是打印垃圾还是如何打印我需要的值
- 是什么阻止DOMTimerCoordinator::NextID进入无休止的循环
- 派生类销毁的最佳实践是什么
- 'for (auto c : str)' c到底是什么?
- 在 Objective-C++ 中应用于__weak指针时,通过关键字推导类型"auto"规则是什么?
- auto&x = const int *的类型是什么?
- C++11 中的"auto var = {condition} ? 1 : 1.0"是什么类型?是双精度还是整数?
- auto在c++ 11中的含义改变;请删除它这是什么意思
- 错误 C2274:使用 auto 进行 boost::p osix_time::time_duration 时出现"函数样式转换"的原因是什么?
- decltype(auto)的一些用途是什么?
- 在 S 被解析为 for(auto &s :text)后,S 应该是什么类类型?
- 使用 auto 在 C++ 中声明 lambda 变量的首选方法是什么