C++ 11
14.8.2 - 模板参数扣除 -
[temp.deduct]7替换发生在函数类型和模板参数声明中使用的所有类型和表达式中.表达式不仅包括常量表达式如那些出现在数组边界或无类型模板参数而且一般表达式(即非常量表达式)的内部
sizeof,decltype和其它上下文允许非常量表达式.
C++ 14
14.8.2 - 模板参数扣除 -
[temp.deduct]7替换发生在函数类型和模板参数声明中使用的所有类型和表达式中.表达式不仅包括常量表达式如那些出现在数组边界或无类型模板参数而且一般表达式(即非常量表达式)的内部
sizeof,decltype和其它上下文允许非常量表达式.替换以词汇顺序进行,并在遇到导致演绎失败的条件时停止.
添加的句子明确说明了在C++ 14中处理模板参数时的替换顺序.
替换顺序通常不会引起很多关注.我还没有找到一篇关于其重要性的论文.也许这是因为C++ 1y尚未完全标准化,但我认为必须引入这样的改变是有原因的.
问题:
14.8.2段的C++ 11标准的/ 8指定在其下的取代失败作出或不会导致"硬"编译错误的条件(从而引起编译失败),或者在"软"差错这将只是导致编译器从一组候选中丢弃模板以进行重载解析(不使编译失败并启用众所周知的SFINAE习语):
如果替换导致无效的类型或表达式,则类型推导失败.如果使用替换参数写入,则无效的类型或表达式将是格式错误的.[注意:访问检查是作为替换过程的一部分完成的.-end note] 只有函数类型的直接上下文中的无效类型和表达式及其模板参数类型才会导致演绎失败.[...]
单词" 直接上下文 "在整个C++ 11标准中仅出现8次,并且每次出现以下(或作为其一部分)以下(非规范)文本的实例时:
[注:在取代的类型和表达式的计算可导致副作用,例如类模板特和/或功能模板特的实例化,隐含定义的函数的生成等.这样的副作用是不是在"即时上下文"并且可能导致程序格式不正确. - 尾注]
该说明给出了什么叫一个(不是非常慷慨)暗示直接背景,但至少对我来说这往往是不足以决定一个替代是否是或不应该造成"硬"的编译错误.
题:
您能否提供一个解释,一个决策程序和/或一些具体的例子来帮助弄清楚在什么情况下替换错误在函数类型及其模板参数类型的" 直接上下文 "中发生和不发生?
感谢C++ 14,我们很快就能够减少冗长的尾随返回类型; 例如minDavid Abrahams 2011 帖子的一般例子:
template <typename T, typename U>
auto min(T x, U y)
-> typename std::remove_reference< decltype(x < y ? x : y) >::type
{ return x < y ? x : y; }
Run Code Online (Sandbox Code Playgroud)
在C++ 14下,返回类型可以省略,min可以写成:
template <typename T, typename U>
auto min(T x, U y)
{ return x < y ? x : y; }
Run Code Online (Sandbox Code Playgroud)
这是一个简单的示例,但是返回类型推导对于通用代码非常有用,并且可以避免很多复制.我的问题是,对于这样的功能,我们如何整合SFINAE技术?例如,我如何使用std::enable_if限制min函数返回积分类型?
请考虑以下代码:
// -------------------------------------------------------------------------- //
// Preprocessor
#include <array>
#include <vector>
#include <utility>
#include <iostream>
#include <type_traits>
// -------------------------------------------------------------------------- //
// -------------------------------------------------------------------------- //
// Calls a function without arguments if it can be called
template <
class F,
class... Args,
class = decltype(std::declval<F>()())
>
decltype(auto) apply(F&& f)
{
std::cout<<"apply(F&& f)"<<std::endl;
return std::forward<F>(f)();
}
// Calls a function with arguments if it can be called
template <
class F,
class Arg,
class... Args,
class = decltype(std::declval<F>()(
std::declval<Arg>(), std::declval<Args>()...
))
>
decltype(auto) apply(F&& …Run Code Online (Sandbox Code Playgroud)