【问题标题】:inheriting from class of specialized self?从专门的自我类继承?
【发布时间】:2012-01-15 09:18:17
【问题描述】:

这是有效的 C++ 吗?

template<class category>
class any_iterator : public any_iterator<void>
{ 
public:
        typedef any_iterator<void> any_iter_void;

        any_iterator() : any_iter_void() {}
};
template<>
class any_iterator<void>
{ 
public:
        typedef any_iterator<void> any_iter_void;

        any_iterator() {}
        void foo() {};
};

int main() {
    any_iterator<int> a;
    a.foo();
}

MSVC10 在\WALL 上接受它并且没有错误/警告,但gcc-4.5.1 抱怨:

prog.cpp:3:5: 错误:无效使用不完整类型 'class any_iterator'
prog.cpp:2:11:错误:“类 any_iterator”的声明
prog.cpp:在函数“int main()”中:
prog.cpp:21:11:错误:“类 any_iterator”没有名为“foo”的成员
prog.cpp: 在构造函数中'any_iterator::any_iterator() [with category = int]':
prog.cpp:20:27: 从这里实例化
prog.cpp:7:44:错误:类型“any_iterator”不是“any_iterator”的直接基础

有人可以引用标准来说明这是否应该编译吗?我认为这是 MSVC 中的一个错误。

作为说明,我知道正确的做法是声明类,专门化根,然后定义一般情况,这就是我将对我的代码执行的操作,但我想知道这里哪个编译器出错了?

【问题讨论】:

  • MSVC 缺少两阶段名称查找的问题再次出现。
  • 与其对基类使用特化,为什么不完全使用不同的类?
  • MSVC 的实现似乎更方便 IMO。
  • @MarkRansom:(真正的)类形成一个层次结构,用户可以在其中添加类型(它们是迭代器类别)。因此,any_iterator&lt;void&gt; 作为一切的根源是有意义的。

标签: c++ templates inheritance template-specialization


【解决方案1】:

要从一个类型继承,该类型必须是完整的。稍微重新安排一下就可以解决问题:

template<class category>
class any_iterator;

template<>
class any_iterator<void>
{ 
public:
    typedef any_iterator<void> any_iter_void;

    any_iterator() { }
    void foo() { }
};

template<class category>
class any_iterator : public any_iterator<void>
{ 
public:
    typedef any_iterator<void> any_iter_void;

    any_iterator() : any_iter_void() { }
};

int main()
{
    any_iterator<int> a;
    a.foo();
}

代币标准报价:

C++11,§10/2:

由 base-type-specifier 表示的类型应该是一个非未完全定义类的类类型;这个类被称为被定义类的直接基类。

§9.2/2:

类在类说明符的结尾}处被视为完全定义的对象类型(或完整类型)。

【讨论】:

  • 嘿,还有 3 票。 Can someone quote the standard... 和 the correct thing to do is to declare the class, specialize the root, then define the general case...
  • 你想要一个标准的引用来说明一个类型必须是完整的才能从它派生?这不是常识吗?
  • 不一定是这样,我想。您通常可以从尚未专门化的模板类型派生,不是吗?只要它在派生类型被实例化之前是特化的?
  • @Mooing :不需要专门化,但需要一个完整的定义。在没有事先完整定义any_iterator&lt;void&gt; 的情况下执行class any_iterator : public any_iterator&lt;void&gt; 时,any_iterator 本身尚未完成(没有打开{ 更不用说关闭}),因此不能将其指定为基类。
  • @curiousguy :不,这是“您无法备份您所说的任何内容,所以为什么要打扰?”的代号。
【解决方案2】:

10/2:

由基类型说明符表示的类型应该是一个不是不完全定义的类的类类型

这是 MSVC 缺陷的一种表现:缺少两阶段名称解析。

【讨论】:

  • “它缺乏两阶段名称解析。”不仅仅是两阶段查找,它可能实现了旧式模板作为宏“语义”
  • @curiousguy:由于代码可以编译,这意味着它会将模板实例化保存到最后。
猜你喜欢
  • 1970-01-01
  • 2016-04-06
  • 2023-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-22
相关资源
最近更新 更多