SFINAE 表达式无法用 clang 编译
SFINAE expression fails to compile with clang
这看起来像是 clang 中的一个问题(我已经打开了一个错误 here),但我想确保我没有做错。
考虑以下代码:
#include <type_traits>
#include <cstddef>
template<std::size_t N, std::size_t M, std::enable_if_t<not (N>M)>* = nullptr> // (1)
struct S: public S<N+1, M> { };
template<std::size_t N>
struct S<N, N> { };
int main() {
S<0, 1> c{};
}
编译失败,出现以下错误:
8 : error: non-type template argument specializes a template parameter with dependent type 'std::enable_if_t M)> *' (aka 'typename enable_if M), void>::type *')
struct S { };
相同的代码使用以下行而不是 (1) 按预期工作:
template<std::size_t N, std::size_t M, typename = std::enable_if_t<not (N>M)>>
SFINAE表达式几乎一样。它基于 std::enable_if_t
的专业化,我希望这两个示例的结果相同(成功或失败)。
我的期望错了吗?
请注意,GCC 在任何一种情况下都可以正常工作。
我认为这实际上是一个 gcc 错误,因为 [temp.class.spec]:
The type of a template parameter corresponding to a specialized
non-type argument shall not be dependent on a parameter of the
specialization. [ Example:
template <class T, T t> struct C {};
template <class T> struct C<T, 1>; // error
template< int X, int (*array_ptr)[X] > class A {};
int array[5];
template< int X > class A<X,&array> { }; // error
—end example ]
在您的示例中,第三个模板参数的类型取决于参数。当你把它换成 typename = std::enable_if_t<...>
时,这条规则就不再适用了。
注意:有什么理由在这里使用 SFINAE,而不是 static_assert
-ing?
这看起来像是 clang 中的一个问题(我已经打开了一个错误 here),但我想确保我没有做错。
考虑以下代码:
#include <type_traits>
#include <cstddef>
template<std::size_t N, std::size_t M, std::enable_if_t<not (N>M)>* = nullptr> // (1)
struct S: public S<N+1, M> { };
template<std::size_t N>
struct S<N, N> { };
int main() {
S<0, 1> c{};
}
编译失败,出现以下错误:
8 : error: non-type template argument specializes a template parameter with dependent type 'std::enable_if_t M)> *' (aka 'typename enable_if M), void>::type *')
struct S { };
相同的代码使用以下行而不是 (1) 按预期工作:
template<std::size_t N, std::size_t M, typename = std::enable_if_t<not (N>M)>>
SFINAE表达式几乎一样。它基于 std::enable_if_t
的专业化,我希望这两个示例的结果相同(成功或失败)。
我的期望错了吗?
请注意,GCC 在任何一种情况下都可以正常工作。
我认为这实际上是一个 gcc 错误,因为 [temp.class.spec]:
The type of a template parameter corresponding to a specialized non-type argument shall not be dependent on a parameter of the specialization. [ Example:
template <class T, T t> struct C {}; template <class T> struct C<T, 1>; // error template< int X, int (*array_ptr)[X] > class A {}; int array[5]; template< int X > class A<X,&array> { }; // error
—end example ]
在您的示例中,第三个模板参数的类型取决于参数。当你把它换成 typename = std::enable_if_t<...>
时,这条规则就不再适用了。
注意:有什么理由在这里使用 SFINAE,而不是 static_assert
-ing?