【问题标题】:How to specialize a template sub-class?如何专门化模板子类?
【发布时间】:2023-08-13 10:42:01
【问题描述】:

我试图在另一个类中专门化一个模板类,但编译器不让我这样做。该代码在 Foo 类之外工作,但不在内部,我希望 struct Bla 对 Foo 类是私有的。

class Foo {
   template<typename ... Ts> struct Bla; 
   template<> struct Bla<> { static constexpr int x = 1; };
};

error: explicit specialization in non-namespace scope 'class Foo'

【问题讨论】:

    标签: c++ templates template-specialization


    【解决方案1】:

    你不能在课堂上专攻,使用:

    class Foo {
    public: // so we can test it easily
       template<typename ... Ts> struct Bla; 
    };
    
    // specialize it outside the class
    template<> class Foo::Bla<> { static constexpr int x = 1; }; 
    
    int main()
    {
        std::cout << Foo::Bla<>::x;
    }
    

    【讨论】:

    • 谢谢,这正是解决方案。
    • @GoswinvonBrederlow 注意我在这里使用了public,所以我可以显示Bla::x。但是我猜你正在使用friend 或通过成员函数显示,在这种情况下你应该没问题。
    • 这让我思考。这不允许侵犯班级的隐私吗? class Foo { static constexpr int y = 1; public: template&lt;typename ... Ts&gt; struct Bla; }; template&lt;&gt; struct Foo::Bla&lt;&gt; { static constexpr int x = y; }; Foo::y 是私有的,但是通过专门化 Bla,任何 Foo 用户都可以通过 Bla::x 访问它。
    • @GoswinvonBrederlow 我的答案太长,无法在此处发布。查看*.com/q/424104/3093378 并搜索“后门”
    • @GoswinvonBrederlow 这可能正是您的意思:ideone.com/dBV0eU
    【解决方案2】:

    您根本无法做到这一点。该错误很好地总结了它。类模板只能在命名空间范围内专门化。 class Foo 不是命名空间。

    您可以在类外部执行此操作,根据标准 [temp.class.spec] 中的示例:

    类模板的部分特化可以在其所在的任何命名空间范围内声明或重新声明。 可以定义定义(14.5.1 和 14.5.2)。 [示例:

     template<class T> struct A {  
         struct C {
             template<class T2> struct B { };
         };
     };
    
     // partial specialization of A<T>::C::B<T2>
     template<class T> template<class T2>
       struct A<T>::C::B<T2*> { };
    
    A<short>::C::B<int*> absip; // uses partial specialization
    

    ——结束示例]

    【讨论】:

    • 赞成标准报价,你真的很快:)
    • @vsoftco 从模板章节开始并继续搜索“范围”:)
    • 是的,我知道它是如何工作的,但我还是太懒了:)