c++ - 可以将其类型用推导类类型的占位符指定的非类型模板参数传递给 C++2a 中的另一个模板吗?
问题描述
template<auto>
struct S {};
template<S>
struct T {};
using T0 = T<S<0>{}>; // compiles
template<S s>
using T1 = T<s>; // fails
T0
使用 GCC 9.1 编译但T1
不:
error: class template argument deduction failed
error: no matching function for call to 'S(S<...auto...>)'
这是 C++2a 中的预期行为吗?
编辑: 每当推导类型时,编译失败似乎都会发生,而不是特别是在使用推导类类型的占位符时:
template<auto s>
using T1 = T<s>; // also fails
解决方案
T0
应该是病态的,因为S<0>
不具有很强的结构平等性。
T1
应该是不正确的,不需要诊断,因为就目前而言,没有任何专业化T1
是有效的(因为没有专业化S
具有很强的结构平等性)。
这是因为对类类型作为非类型模板参数的要求来自[temp.param]/4:
非类型模板参数应具有以下类型之一(可选 cv 限定):
- 具有强结构相等性的文字类型([class.compare.default]),
- 左值引用类型,
- 包含占位符类型 ([dcl.spec.auto]) 的类型,或
- 推导类类型的占位符 ([dcl.type.class.deduct])。
template<S>
struct T {};
属于最后一种情况。但是当我们尝试时,我们从 CTAD中T<S<0>{}>
推断出占位符 ,我们点击[temp.arg.nontype]/1:S
S<0>
如果模板参数声明([temp.param])不允许推导参数类型,则程序格式错误。
这让我们回到了最初的参考,现在我们需要一种叫做“强结构平等”的东西。这在[class.compare.default]/4中定义为:
如果给定type的左值,则类型 C 具有强结构相等性:
x
const C
C
是非类类型,并且x <=> x
是类型std::strong_ordering
or的有效表达式std::strong_equality
,或
C
是一个类类型,其中所有以下内容都成立:
- 的所有
C
基类子对象和非静态数据成员都具有很强的结构相等性。C
没有可变或易失的非静态数据成员。- 在 的定义结束时
C
,为表达式执行的重载决策成功并找到在 的定义中定义为默认值x == x
的友元或公共成员运算符。==
C
在我们的例子中,我们是一个类类型,但是虽然我们所有的子对象都具有很强的结构相等性(很简单,因为我们没有子对象),但我们没有适当的operator==
. 要解决这个问题:
template <auto>
struct S {
friend bool operator==(S const&, S const&) = default;
};
现在一切都应该编译(但不是因为 gcc 还不完全支持这一点,实际上甚至不允许你声明所需的 defaulted operator==
)。
推荐阅读
- java - 如何从对象调用覆盖方法
- angular - localhost:4200 和 localhost:4200/projectName 有什么区别?
- highcharts - 使用 highcharts-vue 和 axios 绘制可变数量的系列
- spring - 用于实践的 Spring 和 Hibernate 项目
- tcl - 如何从 -command 选项中的代码获取结果
- reactjs - 如何为每个 Material-UI TableRow 添加 react-router?
- python - python pandas不计算订单对
- javascript - 在发送到服务器之前编辑数据(特别是浏览器指纹)?
- canvas - 三.js球体改变透明度无效?
- java - 春季百里香实现