专门化成员模板而不专门化其父模板

发布于 2024-08-16 21:35:35 字数 876 浏览 8 评论 0原文

我有一个嵌套在另一个模板中的类模板。部分专业化它很容易:我只需声明另一个 template< … > 块位于其父级内。

但是,我需要另一个部分专业化来指定其所有本地模板参数。这使其成为一个明确的专业化。无论出于何种原因,显式专业化都必须在命名空间范围内。要在其父类外部声明它,必须指定父类,这需要非空模板参数列表。这意味着部分专业化。部分专业化就是我正在做的事情,它应该在任意外部范围内工作。但是 GCC 和 Comeau 都无法通过部分特化形式参数来识别父提名中的模板参数。

template< class X > struct A {
    template< class Y > struct B; // initial declaration OK

    template< class Z >
    struct B< A< Z > > {}; // partial OK as long as there's a local arg

    template<> // ERROR: this syntax triggers explicit specialization
    struct B< int > {};
};

template<> // ERROR: can't nest template<>s here (why?)
template< class X > // ERROR: can't deduce X from type of A<X>::B<int> (why?)
struct A< X >::B< int > {};

(我留下了所有非工作代码;适当地注释它以试图理解。)

I have a class template nested inside another template. Partially specializing it is easy: I just declare another template< … > block inside its parent.

However, I need another partial specialization that happens to specify all its local template arguments. This makes it into an explicit specialization. Explicit specializations, for whatever reason, must be at namespace scope. To declare it outside its parent class, the parent must be nominated, which requires a non-empty template argument list. This implies partial specialization. Partial specialization is what I'm doing, and it's supposed to work at arbitrary outer scope. But both GCC and Comeau fail to identify the template parameter in the parent nomination with the partial specialization formal arguments.

template< class X > struct A {
    template< class Y > struct B; // initial declaration OK

    template< class Z >
    struct B< A< Z > > {}; // partial OK as long as there's a local arg

    template<> // ERROR: this syntax triggers explicit specialization
    struct B< int > {};
};

template<> // ERROR: can't nest template<>s here (why?)
template< class X > // ERROR: can't deduce X from type of A<X>::B<int> (why?)
struct A< X >::B< int > {};

(I left all my non-working code in; comment it appropriately to attempt to make sense.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

爱的故事 2024-08-23 21:35:35

根据 C++ 标准 14.7.3/18 是非法的:

.... 声明不得显式特化类成员
template 如果它的封闭类模板没有显式专门化
以及。

It is illegal under C++ standard 14.7.3/18:

.... the declaration shall not explicitly specialize a class member
template if its enclosing class templates are not explicitly specialized
as well.

提赋 2024-08-23 21:35:35

我倾向于不会过多使用嵌套类。我的主要抱怨是它们倾向于使嵌套类的代码变得臃肿。

因此,我建议另一种解决方法:

namespace detail
{
  template <class X, class Z> class BImpl;
  template <class X, class Z> class BImpl<X, A<Z> > {};
  template <class X> class BImpl<X,int> {};
}

template <class X>
class A
{
  template <class Z> struct B: BImpl<X,Z> {};
};

只需注意,如果有的话,它需要将 X 作为参数传递给 BImpl您还希望专注于A。有趣的是,在这种情况下,我最终只获得了部分专业化!

I tend not to use nested classes too much. My main complaint is that they have a tendency to bloat the code of the class they are nested in.

I would therefore propose another workaround:

namespace detail
{
  template <class X, class Z> class BImpl;
  template <class X, class Z> class BImpl<X, A<Z> > {};
  template <class X> class BImpl<X,int> {};
}

template <class X>
class A
{
  template <class Z> struct B: BImpl<X,Z> {};
};

Just note that it requires to pass X as an argument to BImpl if ever you wish to also specialize A. Funny thing is that in this case, I end up with only partial specialization!

栩栩如生 2024-08-23 21:35:35

复杂的东西。你的初始代码是ICE的VC10 Beta2,不错。

首先,我认为你有这个倒退:

template<> 
template< class X > 
struct A< X >::B< int > {};

X是结构A的模板参数,而B是完全专门化的,所以我认为它应该是这样的:

template< class X > 
template<> 
struct A< X >::B< int > {};

但即使这样也无法编译。不过,错误文本实际上很有用:

a.cpp a.cpp(11):错误C3212:
'A::B' :显式
模板成员的特化
必须是显式成员
专业化
a.cpp(8) :参见 'A::B' 的声明

看起来只有当您也完全专门化 A 时,完全专门化 B 才是合法的。

编辑:好的,我收到某人的回复谁能对此进行权威发言——换句话说,这是标准中一个非常模糊的领域,并且是 C++ 委员会清理它的一个开放问题(“它”是类模板成员的显式专业化)。短期内,建议是“不要这样做”。

Complex stuff. Your initial code ICE's VC10 Beta2, nice.

First off, I think you have this backwards:

template<> 
template< class X > 
struct A< X >::B< int > {};

X is a template param to struct A, and B is the one fully specialized, so I think it should be this:

template< class X > 
template<> 
struct A< X >::B< int > {};

But even this fails to compile. The error text is actually useful, though:

a.cpp a.cpp(11) : error C3212:
'A::B' : an explicit
specialization of a template member
must be a member of an explicit
specialization
a.cpp(8) : see declaration of 'A::B'

It looks like it is only legal to fully specialize B if you also fully specialize A.

Edit: Ok, I heard back from someone who can speak authoritatively on this - to paraphrase, this is a very murky area in the standard, and it's an open issue with the C++ Committee to clean it up ("it" being explicit specializations of members of class templates). In the near term, the advice is "Don't do that".

如梦亦如幻 2024-08-23 21:35:35

至少这在 VC 2010 中有效。但是,我无法编写 def。 fun() 的“int”在类声明之外。
编辑:不幸的是 g++ 也有编译问题。
编辑:下面的代码适用于 VC 2010。

template<typename X>
class A
{
public:
    A()
    {

    }

    template<typename Y>
    struct B
    {
        void fun();
    };

    template<>
    struct B<int>
    {
        void fun()
        {
            cout << "Specialized version called\n";
        }
        //void fun();
    };



public:

    B<X> b;
};



template<typename X>
template<typename Y>
void A<X>::B<Y>::fun()
{
    cout << "templated version called\n";
}

int main()
{
   A<int> a;
    a.b.fun();
    A<float> a1;
    a1.b.fun();
}

Atleast this works in VC 2010. But, I am unable to write the def. of fun() for "int" outside the class declaration.
EDIT: Unfortunately g++ has also compilations issues.
EDIT: The code below worked on VC 2010.

template<typename X>
class A
{
public:
    A()
    {

    }

    template<typename Y>
    struct B
    {
        void fun();
    };

    template<>
    struct B<int>
    {
        void fun()
        {
            cout << "Specialized version called\n";
        }
        //void fun();
    };



public:

    B<X> b;
};



template<typename X>
template<typename Y>
void A<X>::B<Y>::fun()
{
    cout << "templated version called\n";
}

int main()
{
   A<int> a;
    a.b.fun();
    A<float> a1;
    a1.b.fun();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文