简体   繁体   English

模板 class 中的部分特化模板 static constexpr

[英]Partially specialized template static constexpr in template class

(A toy, minimal not-working example) (一个玩具,最小的不工作示例)

The next code won't compile with cpp20/17:下一个代码不能用 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;
}

With the error of "Expression did not evaluate to constant" regarding the last line in the struct.关于结构中的最后一行,出现“表达式未计算为常量”的错误。 However, it does compile with full specialization, or without referencing B:但是,它确实以完全专业化或不引用 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;
};

Why is it so?为什么会这样? How can I make the first struct work?我怎样才能使第一个结构工作?

you cant specialize this way, you could use SFINAE or you may try something like:你不能这样专攻,你可以使用 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;
};

I was able to compile your code by adding template keyword.我能够通过添加模板关键字来编译您的代码。

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;
}

As cited here .正如这里所引用的。

Similarly, in a template definition, a dependent name that is not a member of the current instantiation is not considered to be a template name unless the disambiguation keyword template is used or unless it was already established as a template name:类似地,在模板定义中,不是当前实例化成员的依赖名称不被视为模板名称,除非使用了消歧关键字 template 或除非它已被建立为模板名称:

I don't see anything wrong with the code.我看不出代码有什么问题。

template<typename T>
static constexpr size_t C<T> = B;

This is a partial specialization of the C variable template, which is allowed, also inside the class scope.这是C变量模板的部分特化,在 class scope 内部也是允许的。 It is also more specialized than the primary template.它也比主模板更专业。

B is clearly a constant expression since it has been defined before as constexpr variable. B显然是一个常量表达式,因为它之前已被定义为constexpr变量。 Even if it was declared only as const instead it would still be usable in a constant expression (because it is of integral type).即使它仅被声明为const ,它仍然可以在常量表达式中使用(因为它是整数类型)。 The compiler is wrong to reject it as not a constant expression.编译器将其拒绝为不是常量表达式是错误的。

It seems there are simply a few compiler bugs at play here (GCC seems to not like the variable template partial specialization inside the class scope and MSVC seems to have an issue with the constness of B . Clang does not complain.)似乎这里只有一些编译器错误在起作用(GCC 似乎不喜欢 class scope 中的变量模板部分特化,MSVC 似乎对B的 constness 有问题。Z9375884CF4ED31C834A626C32 不抱怨)

GCC and MSVC are wrong in rejecting the code as the program is well-formed. GCC 和 MSVC 拒绝代码是错误的,因为程序格式正确。

B is a constant expression and can be used as an initializer when initializing C during its partial specialization. B是一个常量表达式,可以在C的部分特化期间用作初始化器。 This is a msvc bug reported here as:这是一个 msvc 错误,此处报告为:

MSVC rejects valid code when using constexpr static data member as initializer . 使用 constexpr static 数据成员作为初始化程序时,MSVC 拒绝有效代码


Moreover, we are allowed to provide a partial specialization for C (as you did).此外,我们可以为C提供部分专业化(如您所做的那样)。 This is a gcc bug reported as:这是一个 gcc 错误报告为:

GCC rejects valid code involving partial specialization of variable template . GCC 拒绝涉及变量模板部分特化的有效代码

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM