[英]Partially specialized template static constexpr in template class
(一个玩具,最小的不工作示例)
下一个代码不能用 cpp20/17 编译:
template<typename TSomeTemplate>
struct A
{
static constexpr size_t B = 1;
template<typename T, typename... Ts>
static constexpr size_t C = 4;
template<typename T>
static constexpr size_t C<T> = B;
};
int main()
{
A<int>::C<int>;
return 0;
}
关于结构中的最后一行,出现“表达式未计算为常量”的错误。 但是,它确实以完全专业化或不引用 B 的方式进行编译:
template<typename TSomeTemplate>
struct Works
{
static constexpr size_t B = 1;
template<typename T, typename... Ts>
static constexpr size_t C = 4;
template<>
static constexpr size_t C<int> = B;
};
template<typename TSomeTemplate>
struct AlsoWorks
{
static constexpr size_t B = 1;
template<typename T, typename... Ts>
static constexpr size_t C = 4;
template<typename T>
static constexpr size_t C<T> = 2;
};
为什么会这样? 我怎样才能使第一个结构工作?
你不能这样专攻,你可以使用 SFINAE 或者你可以尝试类似的东西:
template<typename TSomeTemplate>
struct A
{
static constexpr size_t B = 1;
template<typename T, typename... Ts>
static constexpr size_t C = sizeof...(Ts) == 0 ? B : 4;
};
我能够通过添加模板关键字来编译您的代码。
template<typename TSomeTemplate>
struct A
{
static constexpr size_t B = 1;
template<typename T, typename... Ts>
static constexpr size_t C = 4;
template<typename T>
static constexpr size_t C<T> = B;
};
int main()
{
A<int>::template C<int>;
return 0;
}
正如这里所引用的。
类似地,在模板定义中,不是当前实例化成员的依赖名称不被视为模板名称,除非使用了消歧关键字 template 或除非它已被建立为模板名称:
我看不出代码有什么问题。
template<typename T>
static constexpr size_t C<T> = B;
这是C
变量模板的部分特化,在 class scope 内部也是允许的。 它也比主模板更专业。
B
显然是一个常量表达式,因为它之前已被定义为constexpr
变量。 即使它仅被声明为const
,它仍然可以在常量表达式中使用(因为它是整数类型)。 编译器将其拒绝为不是常量表达式是错误的。
似乎这里只有一些编译器错误在起作用(GCC 似乎不喜欢 class scope 中的变量模板部分特化,MSVC 似乎对B
的 constness 有问题。Z9375884CF4ED31C834A626C32 不抱怨)
GCC 和 MSVC 拒绝代码是错误的,因为程序格式正确。
B
是一个常量表达式,可以在C
的部分特化期间用作初始化器。 这是一个 msvc 错误,此处报告为:
使用 constexpr static 数据成员作为初始化程序时,MSVC 拒绝有效代码。
此外,我们可以为C
提供部分专业化(如您所做的那样)。 这是一个 gcc 错误报告为:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.