由于命名空间,c++ 无法解释的类“尚未声明”错误

c++ Unexplainable class “ has not been declared” error due to namespace

提问人:ByteMe95 提问时间:2/14/2018 最后编辑:François AndrieuxByteMe95 更新时间:11/27/2021 访问量:790

问:

我有一些模板类有两个私有静态成员。 用户定义一个特征结构并将其提供给模板类,然后模板类从中派生。

然后在 c++ 文件中,用户定义静态成员,其中一个成员从另一个成员初始化。 出于某种原因,如果我没有完全指定 arg 的命名空间,我会收到“类尚未声明”错误。只有当我在嵌套命名空间中时,这才是一个问题,如果您在单个顶级命名空间中定义类型,则没有问题,这让我认为这是一个编译器错误。 下面的精简示例,使用 gcc 7.2 编译

template<typename Traits>
struct Base 
{
    static int x;
    static int y;
};

namespace foo::bar
{
    struct BarTraits
    {
    };

    using Bar = Base<BarTraits>;

    template<> int Bar::x = 0;
    template<> int Bar::y( Bar::x );  //error 
    //template<> int Bar::y( foo::bar::Bar::x ); //no error
}
C++ GCC 命名空间

评论

3赞 François Andrieux 2/14/2018
谨防以你的问题无法回答为前提的方式写问题。如果你的错误真的无法解释,那么在这里问它就没有多大意义了。
4赞 user7860670 2/14/2018
您应该在定义 Base 的同一命名空间中定义它们。或者直接从模板参数中借用它们。Traits
2赞 Bo Persson 2/14/2018
其他编译器已经在 中给出了一个错误,说不能在这里定义或重新声明“x”,因为命名空间“bar”没有包含命名空间“Base<foo::bar::BarTraits>”x
0赞 Jive Dadson 2/14/2018
永远不要承认某些东西“让我认为这是编译器错误”。
1赞 StoryTeller - Unslander Monica 2/14/2018
template<> int Bar::y( Bar::x ); 不定义具有初始值设定项的静态数据成员。此处不能对初始值设定项使用圆括号。

答:

0赞 Fedor 11/27/2021 #1

根据 C++ 标准 temp.expl.spec#3

可以在可以定义相应主模板的任何范围内声明显式专业化。

您的代码违反了此声明,因为 和 专门用于 .Bar::xBar::ynamespace foo::bar

由于已知缺陷 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56119,GCC 错误地接受了前两个专业化

以下固定代码

template<typename Traits>
struct Base  {
    static int x;
    static int y;
};

struct BarTraits {};
using Bar = Base<BarTraits>;

template<> int Bar::x = 0;
template<> int Bar::y( Bar::x );

被 GCC、Clang、MSVC 接受:https://gcc.godbolt.org/z/MPxjTzbah