【问题标题】:Defining a template specialization in an anonymous namespace (and compile error C2888)在匿名命名空间中定义模板特化(并编译错误 C2888)
【发布时间】:2020-03-18 08:33:31
【问题描述】:

Nutshell 版本: 为什么我不能在编译单元/cpp 文件内的匿名命名空间中定义仅在当前编译单元中有用的模板特化(std-lib 类型)?

加长版:

我有一个类型,它只是一个 cpp 文件中的快速助手,我们称之为struct Helper。因为它只在那个编译单元中使用,所以它是在 cpp 内的匿名命名空间中声明和定义的。

因为我想要std::unordered_set<Helper>,所以我必须专攻std::hash。当我现在尝试在同一个匿名命名空间中定义它时,我得到一个C2888 'std::hash<'anonymous-namespace'::Helper>': symbol cannot be defined within namespace 'anonymous-namespace'。这是为什么呢?

我也尝试在 AN 中添加 using namespace std 和类似的东西,但无济于事。

/* This doesn't work */

namespace
{
    struct Helper
    {
        int member1;
        bool member2;
    };

    using namespace std;
    template<>
    struct std::hash<Helper>
    {
        size_t operator()(const Helper& helper) const
        {
            return 12345; /* how it's really generated is irrelevant here */
        }
    };
}

当然,我可以将专业化放在 AN 之外,这样就可以了。我只是想了解为什么它在里面时

/* This works, but why doesn't the other? */

namespace
{
    struct Helper
    {
        int member1;
        bool member2;
    };
}

template<>
struct std::hash<Helper>
{
    size_t operator()(const Helper& helper) const
    {
        return 12345; /* how it's really generated is irrelevant here */
    }
};

【问题讨论】:

    标签: c++ templates namespaces template-specialization


    【解决方案1】:

    属于命名空间std 的符号必须在包含std 的命名空间中定义,这意味着您必须在全局命名空间中定义它。

    这是来自C2888的示例:

    namespace M {
       namespace N {
          void f1();
          void f2();
       }
    
       void N::f1() {}   // OK: namspace M encloses N
    }
    
    namespace O {
       void M::N::f2() {}   // C2888 namespace O does not enclose M
    }
    

    [temp.expl.spec/9] 来自 C++20 草案:

    模板显式特化位于定义模板的命名空间范围内。 [ 例子:

    namespace N {
      template<class T> class X { /* ... */ };
      template<class T> class Y { /* ... */ };
    
      template<>
      class X<int> { /* ... */ };     // OK: specialization in same namespace
    
      template<>
      class Y<double>;                // forward-declare intent to specialize for double
    }
    
    template<>
    class N::Y<double> { /* ... */ }; // OK: specialization in enclosing namespace
    
    template<>
    class N::Y<short> { /* ... */ };  // OK: specialization in enclosing namespace
    

    —结束示例]

    【讨论】:

    • 好的——很高兴知道!但是您能否解释一下为什么,或者指出(至少粗略地)cpp 标准中说明和(希望!)解释的地方?不是我怀疑你,我只是想了解其中的原因。
    • @JohannStudanski 将尝试在标准中找到它,但我不太擅长在其中搜索,因此可能需要一些时间。可能是这样的:eel.is/c++draft/temp.expl.spec#9
    • 谢谢!如果你需要自己搜索,别担心,我不想把这项工作强加给你。如果您从记忆中知道它在哪里(也许是您发布的那个),那就太棒了,否则我也可以自己愉快地挖掘它。
    • @JohannStudanski 好的,很酷。否则,标记问题language-lawyer,吃标准早餐的人就会出现:-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-12
    • 2018-06-24
    • 2014-04-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多