c++ - 类模板偏特化等价

标签 c++ language-lawyer c++17

什么时候两个不同的类模板偏特化声明匹配?

在下面的代码中有两个偏特化声明:

  • 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 ,“等效但功能不等效的重新声明”:

In an example like

template<typename T, typename U> using X = T;
template<typename T> X<void, typename T::type> f();
template<typename T> X<void, typename T::other> f();

it appears that the second declaration of f is a redeclaration of the first but distinguishable by SFINAE, i.e., equivalent but not functionally equivalent.

Notes from the November, 2014 meeting:

CWG felt that these two declarations should not be equivalent.

这仍然是一个活跃的问题。 gcc 的行为更符合这些不同的愿望。 [temp.alias]/2[temp.alias]/3是相关的透明度规则:

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.

However, if the template-id is dependent, subsequent template argument substitution still applies to the template-id.

这里有冲突。在问题的简化示例中,X<T, U> 相当于 T - 这意味着两个声明的返回类型都是 void - 但替换仍然适用,这并不完全意味着它们是等价的

关于c++ - 类模板偏特化等价,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52255175/

相关文章:

c# - 如何将信息从一个类传递到另一个类

c++ - 如何为 friend 函数中定义的类授予友元?

c++ - 可以在 constexpr 上下文中使用导致未指定(不是未定义!)行为的指针的表达式吗?

c++ - 构造函数中的 const int ref 可以安全地绑定(bind)到文字吗?

c++ - 如何确保 C++ 类模板中非静态数据成员的正确初始化

c++ - 应用程序崩溃说 : Access violation reading location

c++ - Boost Beast 握手 : sslv3 alert handshake failure error

c++ - 有什么区别 - const int x = 5000;和 const int x = 50'00;在 C++ 中?

c++ - 自动模板参数可以传什么有限制吗?

c++ - 如何使用 C++ 模板推断编译时 const char 字符串的大小?