非命名空间范围中的显式专用化不会在GCC中编译

lsmd5eda  于 2022-11-13  发布在  其他
关注(0)|答案(2)|浏览(104)

下面的代码可以在Clang中编译,但不能在GCC中编译:

template<typename T>
struct Widget
{
    template<typename U>
    void foo(U)
    {
    }

    template<>
    void foo(int*)
    {
    }
};

根据C++标准([temp.expl.spec],第2段):
显式专门化可以在任何范围中声明,在该范围中可以定义相应的主模板
这是GCC中的一个bug吗?如果是的话,我如何在它的bug跟踪器中找到它?
以下是GCC的输出:

prog.cc:13:14: error: explicit specialization in non-namespace scope 'struct Widget<T>'
     template<>
              ^

我使用的是GCC HEAD 8.0.1,带有-std=c++2a

daupos2t

daupos2t1#

这应该是一个GCC错误。在任何范围内都应该允许完全的专门化,包括在类定义中。
根据CWG 727,[温度暴露质量标准]第2段从
(强调我)
显式专用化应在包含专用化模板的命名空间中声明。其declarator-id或class-head-name未限定的显式专用化应在模板的最近的封闭命名空间中声明,如果命名空间是内联的,则为(10.3.1 [namespace.def]),从它的封闭命名空间集中的任何命名空间。这样的声明也可以是定义。如果声明不是定义,可以在以后定义专门化(10.3.1.2 [namespace.memdef])。

(强调我)
显式专门化可以在任何范围中声明,在该范围中可以定义相应的主模板(10.3.1.2 [namespace.memdef],12.2 [class.mem],17.6.2 [temp.mem])。
看来GCC没有遵循这一点。

编辑

我已将此问题报告为Bug 85282

bpsygsoo

bpsygsoo2#

如果有人在gcc中修复此问题之前正在寻找解决方法:
可以使用std::is_same_vif constexprgodbolt

template<typename T>
struct Widget
{
    template<typename U>
    void foo(U)
    {
        if constexpr (std::is_same_v<U, int*>) {
            std::cout << "int*\n";
        }
        std::cout << "U\n";
    }

};

相关问题