为sfinae使用别名模板:语言允许吗? [英] Using alias templates for sfinae: does the language allow it?

查看:97
本文介绍了为sfinae使用别名模板:语言允许吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚发现了以下技术.它看起来非常接近建议的概念语法之一,可以在Clang,GCC和MSVC上完美运行.

I have just discovered the following technique. It looks very close to one of proposed concepts syntax, works perfectly on Clang, GCC and MSVC.

template <typename T, typename = typename std::enable_if<std::is_rvalue_reference<T&&>::value>::type>
using require_rvalue = T&&;

template <typename T>
void foo(require_rvalue<T> val);

我试图通过搜索请求(例如"sfinae in type alias")找到它,但一无所获.这种技术有名称吗,语言实际上允许吗?

I tried to find it with search requests like "sfinae in type alias" and got nothing. Is there a name for this technique and does the language actually allows it?

完整示例:

#include <type_traits>

template <typename T, typename = typename std::enable_if<std::is_rvalue_reference<T&&>::value>::type>
using require_rvalue = T&&;

template <typename T>
void foo(require_rvalue<T>)
{
}

int main()
{
    int i = 0;
    const int ic = 0;
    foo(i);            // fail to compile, as desired
    foo(ic);           // fail to compile, as desired
    foo(std::move(i)); // ok
    foo(123);          // ok
}

推荐答案

[...]语言实际上允许它吗?

[...] does the language actually allows it?

关于名字什么也不能说,但是在我看来这是肯定的.

Can't say anything about the name, but this seems to me to be a yes.

相关措辞为 [temp.alias]/2 :

template-id 指代别名模板的特殊化时,它等同于通过将其 template-arguments 替换为而获得的关联类型.别名模板的 type-id 中的> template-parameters .

When a template-id refers to the specialization of an alias template, it is equivalent to the associated type obtained by substitution of its template-arguments for the template-parameters in the type-id of the alias template.

和sfinae规则 [temp.deduct]/8 :

只有在函数类型,其模板参数类型及其 explicit-specifier 的直接上下文中无效的类型和表达式才可能导致推论失败.

Only invalid types and expressions in the immediate context of the function type, its template parameter types, and its explicit-specifier can result in a deduction failure.

采用类型为require_rvalue<T>的参数的行为的确就像我们替换了该别名一样,别名为我们提供了T&&或替换失败-并且该替换失败可以说是在直接上下文中 CWG 1558 (void_t规则),我们添加了 [临时别名]/3 :

Taking an argument of type require_rvalue<T> does behave as if we substitute that alias, which either gives us a T&& or a substitution failure - and that substitution failure is arguably in the immediate context of the substitution and so is "sfinae-friendly" as opposed to being a hard error. Note that even though the defaulted type argument is unused, as a result of CWG 1558 (the void_t rule), we got the addition of [temp.alias]/3:

但是,如果 template-id 是依赖的,则随后的模板参数替换仍然适用于 template-id .

However, if the template-id is dependent, subsequent template argument substitution still applies to the template-id.

这可以确保我们仍然替换为默认的type参数以触发所需的替换失败.

This ensures that we still substitute into the defaulted type argument to trigger the required substitution failure.

问题的第二个未说部分是它是否实际上可以充当转发参考. [temp.deduct.call]/3中有此规则:

The second unsaid part of the question is whether this actually can behave as a forwarding reference. The rule there is in [temp.deduct.call]/3:

转发参考是对cv不合格模板参数的右值引用,该参数不代表类模板的模板参数(在类模板参数推导期间[[over.match.class.deduct ])).如果P是转发引用,并且参数是左值,则使用类型对A的左值引用"代替A进行类型推导.

A forwarding reference is an rvalue reference to a cv-unqualified template parameter that does not represent a template parameter of a class template (during class template argument deduction ([over.match.class.deduct])). If P is a forwarding reference and the argument is an lvalue, the type "lvalue reference to A" is used in place of A for type deduction.

是否具有一个模板参数的别名模板(其关联类型是对其cv不合格模板参数的右值引用)被视为转发参考?好吧,[temp.alias]/2表示require_rvalue<T>等同于T&&,而T&&是正确的事情.可以这么说...是的.

Is an alias template with one template parameter whose associated type is an rvalue reference to its cv-unqualified template parameter considered a forwarding reference? Well, [temp.alias]/2 says that require_rvalue<T> is equivalent to T&&, and T&& is the right thing. So arguably... yeah.

所有编译器都将其视为此类,这无疑是一个不错的验证.

And all the compilers treat it as such, which is certainly a nice validation to have.


不过,请注意


Although, note the existence of CWG 1844 and the lack of actual definition for immediate context, and the example there which also relies upon a substitution failure from a defaulted argument - which the issue states has implementation divergence.

这篇关于为sfinae使用别名模板:语言允许吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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