两个不同的类模板部分特化声明何时匹配?
在下面的代码中有两个部分特化声明:
-
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]似乎不适用于此处 .
标准对部分专业化声明等效性的说法是什么?
1 回答
这是CWG 1980,"Equivalent but not functionally-equivalent redeclarations":
这仍然是一个活跃的问题 . gcc的行为更符合这些不同的愿望 . [temp.alias]/2和[temp.alias]/3是相关的透明度规则:
这里有冲突 . 在该问题的简化示例中,
X<T, U>
等同于T
- 这意味着两个声明只有void
的返回类型 - 但替换仍然适用,而且它不等同于't exactly mean they' .