替代失败是否有依赖非类型模板参数的错误? [英] Is substitution failure an error with dependent non-type template parameters?
问题描述
假设我有这些模板别名:
enum class enabler {};
template< typename T>
using EnableIf = typename std :: enable_if< T :: value,enabler> :: type;
template< typename T>
使用DisableIf = typename std :: enable_if<!T :: value,enabler> :: type;
我可以在GCC中执行以下操作:
#include< iostream>
template< typename T,EnableIf< std :: is_polymorphic< T> = {}>
void f(T){std :: cout< 是polymorphic\\\
; }
template< typename T,DisableIf< std :: is_polymorphic< T> = {}>
void f(T){std :: cout< is not polymorphic\\\
; }
struct foo {virtual void g(){}};
int main(){
f(foo {});
f(int {});
}
打印:
< blockquote>
是多态的
不是多态的
/ p>
使用clang代码不能编译。它会产生以下错误消息。
test.cpp:11:58:error:expected expression
template< typename T,EnableIf< std :: is_polymorphic< T> = {}>
^
test.cpp:14:59:error:expected expression
template< typename T,DisableIf< std :: is_polymorphic< T& = {}>
^
test.cpp:20:3:error:没有匹配函数调用'f'
f(foo {});
^
test.cpp:12:6:注意:候选模板被忽略:不能推断模板参数''
void f(T){std :: cout< 是polymorphic\\\
; }
^
test.cpp:15:6:注意:候选模板被忽略:不能推断模板参数''
void f(T){std :: cout< is not polymorphic\\\
; }
^
test.cpp:21:3:error:没有匹配函数调用'f'
f(int {});
^
test.cpp:12:6:注意:候选模板被忽略:不能推断模板参数''
void f(T){std :: cout< 是polymorphic\\\
; }
^
test.cpp:15:6:注意:候选模板被忽略:不能推断模板参数''
void f(T){std :: cout< is not polymorphic\\\
; }
^
生成4个错误。
应该编译吗?
首先,感谢@ Richard Smith #llvm IRC频道ontc
不幸的是,这不是合法的C ++,因此Clang是正确的: {}
不是表达式但是一个
的支持初始化列表,因此永远不会是一个非常量表达式,在非类型模板参数的初始化器中需要。
§14.3.2[temp.arg.non-type] p1
< >
模板参数应该是
$ b $ 对于整数或枚举类型的非类型模板参数,转换后的常量表达式(5.19),可以使用b- [...]
<类型的模板参数;或
<将是启用程序
中的虚拟值。
Let's say I have these template aliases:
enum class enabler {};
template <typename T>
using EnableIf = typename std::enable_if<T::value, enabler>::type;
template <typename T>
using DisableIf = typename std::enable_if<!T::value, enabler>::type;
I can do the following in GCC:
#include <iostream>
template <typename T, EnableIf<std::is_polymorphic<T>> = {}>
void f(T) { std::cout << "is polymorphic\n"; }
template <typename T, DisableIf<std::is_polymorphic<T>> = {}>
void f(T) { std::cout << "is not polymorphic\n"; }
struct foo { virtual void g() {} };
int main() {
f(foo {});
f(int {});
}
It prints:
is polymorphic
is not polymorphic
Which matches my expectations.
With clang that code does not compile. It produces the following error messages.
test.cpp:11:58: error: expected expression
template <typename T, EnableIf<std::is_polymorphic<T>> = {}>
^
test.cpp:14:59: error: expected expression
template <typename T, DisableIf<std::is_polymorphic<T>> = {}>
^
test.cpp:20:3: error: no matching function for call to 'f'
f(foo {});
^
test.cpp:12:6: note: candidate template ignored: couldn't infer template argument ''
void f(T) { std::cout << "is polymorphic\n"; }
^
test.cpp:15:6: note: candidate template ignored: couldn't infer template argument ''
void f(T) { std::cout << "is not polymorphic\n"; }
^
test.cpp:21:3: error: no matching function for call to 'f'
f(int {});
^
test.cpp:12:6: note: candidate template ignored: couldn't infer template argument ''
void f(T) { std::cout << "is polymorphic\n"; }
^
test.cpp:15:6: note: candidate template ignored: couldn't infer template argument ''
void f(T) { std::cout << "is not polymorphic\n"; }
^
4 errors generated.
Should it compile? Which of the two compilers is faulty?
First and foremost, thanks to @Richard Smith on the #llvm IRC Channel on oftc for the explanation.
Unfortunately, this is not legal C++ and as such Clang is correct: {}
is not an expression but a braced-init-list and as such will never be a constant expression as is needed in the initializer of a non-type template parameter.
§14.3.2 [temp.arg.non-type] p1
A template-argument for a non-type, non-template template-parameter shall be one of:
- for a non-type template-parameter of integral or enumeration type, a converted constant expression (5.19) of the type of the template-parameter; or
- [...]
One solution would be a dummy value in enabler
.
这篇关于替代失败是否有依赖非类型模板参数的错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!