为sfinae使用别名模板:语言允许吗? [英] Using alias templates for sfinae: does the language allow it?
问题描述
我刚刚发现了以下技术.它看起来非常接近建议的概念语法之一,可以在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&&
或替换失败-并且该替换失败可以说是在直接上下文中† 替代",因此对sfinae友好",而不是硬错误.请注意,即使默认类型参数未使用,由于 [临时别名]/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屋!