SFINAE,演绎与实例化 [英] SFINAE, deduction vs. instantiation

查看:201
本文介绍了SFINAE,演绎与实例化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此代码无法在大多数编译器中编译,但一开始我直觉地期望SFINAE保护我:

This code fails to compile in most compilers but at first I intuitively expected SFINAE to protect me:

typedef void (*A)();

template < typename T >
struct a_metafun { typedef typename T::type type; };

template < typename T >
typename a_metafun<T>::type f(T) {}

template < typename T>
void f(T(*)()) {}

int main() { f(A()); }

我可以通过至少两种方式解决这个问题:

I can fix the problem in at least two ways:

1)将metafunf()的定义更改为:

1) Change the definition of "metafun" f() to:

类型名T>
typename T :: type f(T){}

2)定义a_metafun一个类型,如果T有一个,如果它不...但是实例化没有错误任何一种方式:

2) define "a_metafun" such that it analyzes T and has a type if T has one and doesn't if it doesn't...but instantiates without error either way:

BOOST_MPL_HAS_XXX_TRAIT_DEF(type)

typedef < template T, bool = has_type<T>::value >
struct a_metafun { };

typedef < template T >
struct a_metafun<T, true> { typedef typename T::type type };

查看14.8.2(C ++ 03) SFINAE可以应用什么条件。有更好的地方看吗?即使在扣除另一个模板的情况下,在已经推导的模板实例化中失败也不会包含在此列表中。

Upon looking at 14.8.2 (C++03) it looks to me like it specifies exactly under what conditions SFINAE can apply. Is there a better place to look? Failure within the instantiation of an already deduced template, even during the deduction of another, would not seem to be included in this list.

我已经采取了解释的另一个方向什么使得这是非法的,是a_metafun的扣除已经发生,其内部的实例化是导致错误的原因。 SFINAE不适用于实例化期间,但只有在扣除,或我错了吗?在第二种情况下,a_metafun是正确的,并且完全实例化,但它根本没有类型的定义,这意味着模板试图实例化它是由于替换失败。

Another direction I've taken to interpreting what makes this illegal is that the deduction of a_metafun has already taken place and the instantiation of its innards is what is causing the error. SFINAE doesn't apply during instantiation but only during deduction, or am I wrong there? In the second case though, a_metafun is being correctly, and well-formedly instantiated but it simply has no "type" definition within, which means the template attempting to instantiate it is failing due to substitution.

基本上我想知道在标准中是什么指定我目睹的行为。我试过的每一个编译器都抱怨,甚至来了。我认为他们是这样做的正确,我只是不完全确定为什么。

Basically I'm wondering what in the standard specifies the behavior I'm witnessing. Every compiler I've tried complains, even comeau. I'm of the opinion that they are correct in doing so, I'm just not completely sure as to why.

所以,专家...什么是什么?为什么类型的实例化,即使在f()中的推导的上下文中导致错误,而不是SFINAE排除?

So, experts...what's what? Why does the instantiation of type, even in the context of deduction in f() cause an error rather than SFINAE exclusion?

推荐答案

在C ++ 03规范中,SFINAE的规则有点模糊,允许编译器作者去任何长度,以找到替代失败,导致SFINAE。来自C ++ 03的相关文本§14.8.2/ 2说:

In C++03 specification, the rule of SFINAE is a little vague, allowing compiler authors to go to any length to find substitution failure to result in SFINAE. The relevant text §14.8.2/2 from C++03 says,


-

- [...] If a substitution in a template parameter or in the function type of the function template results in an invalid type, type deduction fails [...]

它进一步解释了失败的几个原因,但没有人实际上说在什么时候替代失败应该被视为SFINAE。所以我想,你的代码可能在C ++ 03中工作正常(或者可能不会,这取决于编译器作者如何解释文本,这是令人困惑的我反正)。

It further explains few reasons for failure, but none of them actually says at what point the substitution failure should be considered as SFINAE. So I guess, your code may work fine in C++03 (or may not, depending on how the compiler authors interpret the text. It is confusing to me anyway).

但是C ++ 11中的措辞已经改进,消除了模糊。它在§14.8.2/ 8中说,

But the wordings in C++11 has been improved removing the vagueness. It says in §14.8.2/8,


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

If a substitution results in an invalid type or expression, type deduction fails. An invalid type or expression is one that would be ill-formed if written using the substituted arguments. [ Note: Access checking is done as part of the substitution process. —end note ] Only invalid types and expressions in the immediate context of the function type and its template parameter types can result in a deduction failure.

术语立即上下文很有趣,我认为它适用于您的情况。更具体地说,元函数 a_metafun 中的替换失败不被认为是函数类型的立即上下文。它在C ++ 11中不合格,而不是SFINAE。

The term "immediate context" is interesting, and I think it applies to your situation. More specifically, the substitution failure in the meta-function a_metafun is not considered "immediate context" of the function-type. It is ill-formed in C++11, not SFINAE.

这篇关于SFINAE,演绎与实例化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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