什么时候两个不同的类模板局部特化声明匹配?
在下面的代码中,有两个部分特化声明:
S<constrain<T,has_accept_>, void>
S<constrain<T,has_visit_>, void>
constrain
是一个别名模板,它等于T
,但使用enable_if
技巧将第二个参数作为概念进行约束。GCC认为这两个部分特化是不同的,但是Clang和MSVC认为它们是等效的,因此拒绝了代码:
#include <type_traits>
#include <utility>
using namespace std;
template<class T,class=void>
struct has_accept
:false_type{};
template<class T>
struct has_accept<T,void_t<decltype(declval<const T&>().accept())>>
:true_type{};
template<class T,class=void>
struct has_visit
:false_type{};
template<class T>
struct has_visit<T,void_t<decltype(declval<const T&>().visit())>>
:true_type{};
//pre c++17 clang/MSVC fix: default argument of template
// used as template template argument not implemented yet
template<class T> using has_accept_ = has_accept<T>;
template<class T> using has_visit_ = has_visit<T>;
template<class T,template<class> class TT,class=enable_if_t<TT<T>::value>>
using constrain = T;
template<class T,class=void>
struct S
:false_type{};
template<class T>
struct S<constrain<T,has_accept_>,void> // (1)
:true_type{};
template<class T>
struct S<constrain<T,has_visit_>,void> // (2)
:true_type{}; // ==> MSVC and Clang: error (2) redefines (1)
我在标准中找不到任何可以指定部分特化等效性的东西。 [temp.type]在这里似乎并不适用。
该标准对部分专业声明的等效性说了什么?
最佳答案
这是CWG 1980,“等效但不等效的重新声明”:
这仍然是一个活跃的问题。 gcc的行为更符合这些不同的愿望。 [temp.alias]/2和[temp.alias]/3是相关的透明度规则:
在这里有冲突。在此问题的简化示例中,X<T, U>
等效于T
-这意味着两个声明都具有void
的返回类型-但是替换仍然适用,并不完全意味着它们等效。
关于c++ - 类模板部分特化的对等,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52255175/