声明具有不同约束的同一模板类的多个版本

Declaration of multiple versions of the same template class with different constraints

提问人: 提问时间:8/13/2023 更新时间:8/15/2023 访问量:82

问:

我正在尝试为任意精度无符号整数类型创建模板类。为了正确地做到这一点,我需要有这个模板类的多个版本,具有不同的约束。 这是我的版本:

template<uint32_t N,bool Destroy=true,bool Const=false>
    requires(N >= 16 and __globals::is_power_2(N) and Destroy and not Const)
class _uint;

template<uint32_t N,bool Destroy,bool Const>
    requires(N >= 16 and __globals::is_power_2(N) and not Destroy and Const)
class _uint;

/* Some necessary declarations */

template <uint32_t N, bool Destroy, bool Const>
    requires (N >= 16 && __globals::is_power_2(N) && Destroy && not Const)
class _uint
{
    // ... Class definition ...
};

template <uint32_t N, bool Destroy, bool Const>
    requires (N >= 16 && __globals::is_power_2(N) && not Destroy && Const)
class _uint
{
    // ... Class definition ...
};

不幸的是,编译器告诉我以下内容:

错误:重新声明“template<unsigned int N, bool Destroy, bool Const> 需要 N >= 16 && is_power_2(std::size_t)(N) && Destroy && !具有不同约束的常量类 _uint'

我不明白为什么我不能这样做。我的愿景是,“requires”语句就像编译器的严格提示,它规定了它应该编译哪个版本的类。因此,在它真正发现冲突之前,它不应该为我有多少个相同类的声明而烦恼,例如,当两个约束满足一组模板参数时。有人可以给我解释一下吗?

我不仅想找出解决方法,还想找出为什么我需要这样做。在引用的重复人员中没有解释为什么我需要使用部分专业化来解决这个问题。对我来说,它仍然很奇怪。

C++ 模板 语言律师 20 C+ +概念

评论

2赞 Pete Becker 8/13/2023
这并不能解决问题,但包含两个连续下划线 () 的名称和以下划线后跟大写字母开头的名称将保留供实现使用。不要在代码中使用它们。__globals
0赞 Iman Abdollahzadeh 8/13/2023
编译器应该如何注意到 和 之间的任何差异?看看这个template<uint32_t N,bool Destroy=true,bool Const=false> requires(N >= 16 and __globals::is_power_2(N) and Destroy and not Const) class _uint;template <uint32_t N, bool Destroy, bool Const> requires (N >= 16 && __globals::is_power_2(N) && Destroy && not Const) class _uint { // ... Class definition ... };
0赞 Nelfeal 8/13/2023
@ImanAbdollahzadeh 这与使用 和 无关。and&&
0赞 Iman Abdollahzadeh 8/13/2023
@Nelfeal 然后它只是模板类的声明和类似的实例化。_uint
1赞 Nelfeal 8/13/2023
@Jarod42 你为什么要通过关闭重复来删除我的评论?我特别没有投票关闭,因为 OP 问“有人可以解释一下吗”,这听起来像是一个关于标准的问题,而不是关于如何处理编译器错误的问题。现在很明显,因为 OP 按照我的建议添加了语言律师标签。副本没有回答这个问题。

答:

0赞 cpplearner 8/15/2023 #1

TL的;DR:类模板不能重载。同一类模板的所有声明必须彼此一致。

这就是语言的设计方式。如果你想改变这一点,请写一份提案

[basic.link]/11

对于实体 E 的任意两个声明:

  • 如果一个声明 E 为类模板,则另一个声明 E 应使用相同类型和等效的模板头 ([temp.over.link])。

[temp.over.link]/6

如果 [...] ,则两个模板头 s 是等价的,如果任一模板头具有 requires-clause,则它们都具有 requires-clause s,并且相应的约束表达式s 是等价的。

[temp.over.link]/5

如果包含两个表达式的函数定义满足一个定义规则,则两个涉及模板参数的表达式被视为等效的,但只要一个表达式中用于命名模板参数的标记被另一个表达式中命名相同模板参数的另一个标记替换,用于命名模板参数的标记可能会有所不同。