什么是“直接上下文”在SFINAE适用的C ++ 11标准中提到? [英] What exactly is the "immediate context" mentioned in the C++11 Standard for which SFINAE applies?

查看:147
本文介绍了什么是“直接上下文”在SFINAE适用的C ++ 11标准中提到?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

C ++ 11标准的第14.8.2 / 8段规定了替换失败将导致或不会导致硬编译错误(从而导致编译失败)或软错误的条件这将导致编译器从一组用于重载解析的候选者中丢弃模板(不会使编译失败并启用众所周知的SFINAE成语):

Paragraph 14.8.2/8 of the C++11 Standard specifies the conditions under which a substitution failure shall or shall not result in a "hard" compilation error (thereby causing compilation to fail) or in a "soft" error which would just cause the compiler to discard a template from a set of candidates for overload resolution (without making compilation fail and enabling the well-known SFINAE idiom):


如果替换导致无效的类型或表达式,类型扣除将失败。无效的类型或表达式
是一个如果使用替换参数写入将是不成形的。 [注意:访问检查是作为替换过程的
部分完成的。 -end note]
的上下文中,只有无效的类型和表达式的函数类型及其模板参数类型可能导致扣除失败
。 [...]

单词 immediate context +11标准,并且每次它们后面跟随(或作为一部分)以下(非规范)文本的实例:

The words "immediate context" appear only 8 times in the whole C++11 Standard, and each time they are followed by (or occur as part of) an instance of the following (non-normative) text:


[注意:替换类型和表达式的求值
可能导致副作用,例如类模板
的特例化和/或函数模板特化,生成隐式定义函数等。
这样的副作用不在直接上下文,并且可能导致程序形式错误。 -end
note]

[Note: The evaluation of the substituted types and expressions can result in side effects such as the instantiation of class template specializations and/or function template specializations, the generation of implicitly-defined functions, etc. Such side effects are not in the "immediate context" and can result in the program being ill-formed.—end note ]

注释提供了一个(非常慷慨的)提示,表示立即上下文的含义,但至少对我来说这通常是不够的

The note gives a (not very generous) hint on what is meant by immediate context, but at least for me this is often not enough to decide whether a substitution is or is not supposed to cause a "hard" compilation error.

QUESTION:

您可以提供解释,决定程序和/或一些具体示例,以帮助确定替换错误在直接上下文的函数类型及其模板参数类型?

Could you provide an explanation, a decision procedure, and/or some concrete examples to help figuring out in what cases a substitution error does and does not occur in the "immediate context" of the function type and its template parameter types?

推荐答案

如果您考虑确定模板参数替换结果所需的所有模板和隐式定义的函数,假设它们是首先生成的,在替换开始之前,那么第一步中发生的任何错误不在直接上下文中,并导致硬错误。

If you consider all the templates and implicitly-defined functions that are needed to determine the result of the template argument substitution, and imagine they are generated first, before substitution starts, then any errors occurring in that first step are not in the immediate context, and result in hard errors.

如果所有这些实例化和隐式定义(其可以包括将函数定义为已删除)可以毫无错误地完成,则在替换期间发生的任何进一步的错误(即,在引用实例化的模板和函数模板的签名中的隐式定义的函数时)不是

If all those instantiations and implicitly-definitions (which might include defining functions as deleted) can be done without error, then any further "errors" that occur during substitution (i.e. while referring to the instantiated templates and implicitly-defined functions in the function template's signature) are not errors, but result in deduction failures.

因此,给定一个这样的函数模板:

So given a function template like this:

template<typename T>
void
func(typename T::type* arg);

以及如果对其他函数的扣除失败将使用的回退 p>

and a "fall-back" that will be used if deduction fails for the other function:

template<typename>
void
func(...);

和类模板:

template<typename T>
  struct A
  {
    typedef T* type;
  };

调用 func< A< int&>>(nullptr )将替换 A< int&> 用于 T T :: type 存在,它必须实例化 A< int&> 。如果我们想象在调用 func< A< int&>(nullptr)之前放置一个显式实例化:

A call to func<A<int&>>(nullptr) will substitute A<int&> for T and in order to check if T::type exists it must instantiate A<int&>. If we imagine putting an explicit instantiation before the call to func<A<int&>(nullptr):

template class A<int&>;

那么会失败,因为它试图创建类型 int& 并且不允许指向引用的指针。我们不能检查替换是否成功,因为实例化 A< int&> 有一个很难的错误。

then that would fail, because it tries to create the type int&* and pointers to references are not allowed. We don't get to the point of checking if substitution succeeds, because there is a hard error from instantiating A<int&>.

现在让我们说明 A 的明确专业化:

Now let's say there's an explicit specialization of A:

template<>
  struct A<char>
  {
  };

调用 func< A< char>>(nullptr)需要实例化 A< char> ,所以想象一下在调用之前程序中某处的显式实例化:

A call to func<A<char>>(nullptr) requires the instantiation of A<char>, so imagine an explicit instantiation somewhere in the program before the call:

template class A<char>;

这个实例是OK的,没有错误,所以我们继续进行参数替换。 A< char> 的实例化工作,但 A< char> :: type 不存在, OK,因为它只在 func 的声明中引用,因此只会导致参数扣除失败,并且后退 ...

This instantiation is OK, there's no error from this, so we proceed to argument substitution. The instantiation of A<char> worked, but A<char>::type doesn't exist, but that's OK because it's only referenced in the declaration of func, so only causes argument deduction to fail, and the fall-back ... function gets called instead.

在其他情况下,替换可能会导致特殊成员函数被隐式定义,可能被删除,这可能会触发其他实例化或隐式定义。如果在生成实例化和隐式定义阶段期间发生错误,那么它们是错误,但是如果成功,但是在替换期间,函数模板签名中的表达式无效。因为它使用不存在的成员或隐式定义为删除的成员,这不是一个错误,只是一个扣除失败。

In other situations substitution might cause special member functions to be implicitly-defined, possibly as deleted, which might trigger other instantiations or implicit definitions. If errors occur during that "generating instantiations and implicit definitions" stage then they're errors, but if that succeeds but during substitution an expression in the function template signature turns out to be invalid e.g. because it uses a member that doesn't exist or something that got implicitly defined as deleted, that's not an error, just a deduction failure.

所以我使用的心理模型是替换需要首先执行准备步骤来生成类型和成员,这可能导致硬错误,但一旦我们完成所有必要的生成,任何进一步的无效使用都不是错误。当然,这一切都是将问题从立即上下文是什么意思?到可以检查此替换之前需要生成哪些类型和成员?所以它可能或可能不会帮助你!

So the mental model I use is that substitution needs to do a "preparation" step first to generate types and members, which might cause hard errors, but once we have all the necessary generation done, any further invalid uses are not errors. Of course all this does is move the problem from "what does immediate context mean?" to "Which types and members need to be generated before this substitution can be checked?" so it may or may not help you!

这篇关于什么是“直接上下文”在SFINAE适用的C ++ 11标准中提到?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆