c++ - 从具有自动参数的模板类继承时基类不明确
问题描述
给定代码
#include <type_traits>
template <auto I, class T>
struct C {};
template <auto I, class T>
void func(C<I, T> c) {}
struct C2 : C<0, int>, C<0u, long> {};
int main() {
static_assert(!std::is_same<C<0, int>, C<0u, long>>::value);
C2 c2;
func<0>(c2); // Error
return 0;
}
我收到错误(来自 GCC):
<source>:15:15: note: 'C<0, T>' is an ambiguous base class of 'C2'
15 | func<0>(c2);
| ^
当实例化 (和) 是明显不同的类型时,类模板 ( ) 怎么会C<I, T>
是一个模棱两可的基类?C<0, int>
C<0u, long>
编辑:我忘记了部分专业化。
解决方案
错误消息可能会稍微好一些。但问题在于尝试进行重载解决方案。理论上可以从 合成两个可能的重载C2
:
void func(C<0, int> c) {}
void func(C<0u, long> c) {}
这是因为类类型的参数可以与接受其基数之一的模板匹配。并且模板参数推导能够推导基类的模板参数。
但这里有个问题:编译器只允许从模板合成一个重载,那么它应该使用哪个基类来合成呢?这是模棱两可的,因此你的错误发生了。编译器不知道它应该使用哪个基类来为特化进行模板参数推导C
。从这个意义上说,这些基础是模棱两可的。
您的编辑没有太大变化。您指定0
,但这仍然可以匹配0u
参数。为了匹配非类型模板参数,相应的模板参数必须是参数类型的转换常量表达式。0
是一个常量表达式,可以转换为0u
常量表达式,反之亦然。因此,指定0
甚至0u
作为显式参数都不会解决歧义。
但是,指定int
orlong
将解决歧义。所以我们可以重写:
template <class T, auto I>
void func(C<I, T> ) {}
然后打电话
func<int>(c2);
推荐阅读
- validation - Flutter FormBuilder下拉验证不起作用
- android - 无法启动活动:Android 9 中的 java.util.ConcurrentModificationException
- python - 使用来自 pi 相机的 python 解码并显示 H.264 卡住的视频序列
- excel - Excel公式分割文本
- ruby-on-rails - Skyscanner Flight search API 与 Ruby on rails6
- python - 根据列值组合行和列名(python)
- asp.net-mvc-5 - 注销重定向到 MVC5 中的登录页面
- c# - 未调用 xUnit 设置函数
- javascript - 在 JavaScript 中使用多个分隔符进行字符串拆分
- java - 如何通过 JNI 将 C 字符串表情符号传递给 Java