如何在命名空间std中转发声明模板类?


131
#ifndef __TEST__
#define __TEST__

namespace std
{
    template<typename T>
    class list;
}

template<typename T>
void Pop(std::list<T> * l)
{
    while(!l->empty())
        l->pop();
}

#endif

并在我的主体中使用了该功能。我得到错误。当然,我知道还有更多的模板参数std::list(我认为分配器)。但是,这是没有意义的。我是否必须知道模板类的完整模板声明才能进行声明?

编辑:我以前没有使用过指针-这是一个参考。我将使用指针进行尝试。


在列表的情况下,第二个参数是默认参数,即std::allocator<T>
nakiya

2
可以认为STL不包含前向声明标头是一种疏忽。另一方面,它的文件经常被包含进来,以至于在编译时可能不会产生任何好处...
Matthieu M.

7
__TEST__是保留的标识符,请勿使用
GManNickG 2010年

Answers:


146

问题不在于您不能向前声明模板类。是的,您确实需要了解所有模板参数及其默认值,才能正确转发声明它:

namespace std {
  template<class T, class Allocator = std::allocator<T>>
  class list;
}

但是namespace std标准明确禁止甚至进行这样的前向声明:唯一允许您放入的std是模板专门化,通常是std::less在用户定义的类型上。如有必要,其他人可以引用相关文本。

只是#include <list>,不用担心。

哦,顺便说一句,任何包含双下划线的名称都保留供实现使用,因此您应使用TEST_H代替__TEST__。它不会产生警告或错误,但是如果您的程序与实现定义的标识符发生冲突,则不能保证它会正确编译或运行:它格式错误。还禁止使用以下划线开头,大写字母开头的名称。通常,除非您知道要处理的是什么魔术,否则不要以下划线开头。


4
为什么禁止在namespace stdbtw中转发声明的东西?
nakiya

4
查看此答案(stackoverflow.com/questions/307343/…)和链接的新闻组讨论。
乔恩·普迪

7
Jon / Nakiya,为什么不使用#pragma once而不是#ifdef。如今,大多数编译器都支持它。
马克·英格拉姆

11
@Mark:因为是#pragma,所以。虽然这是一个选择。
乔恩·普迪

2
有重复的问题重复出现。只需搜索:stackoverflow.com/search?
Jon Purdy 2010年

20

我解决了这个问题。

我正在为C ++(Eclipse Juno)的网络仿真实现OSI层(滑块窗口,级别2)。我有框架(模板<class T>)及其状态(状态模式,前向声明)。

解决方法如下:

*.cpp文件中,您必须包含转发的Header文件,即

ifndef STATE_H_
#define STATE_H_
#include <stdlib.h>
#include "Frame.h"

template <class T>
class LinkFrame;

using namespace std;

template <class T>
class State {

  protected:
    LinkFrame<int> *myFrame;

}

其cpp:

#include "State.h"
#include "Frame.h"
#include  "LinkFrame.h"

template <class T>
bool State<T>::replace(Frame<T> *f){

还有...另一堂课。


34
将任何内容using namespace放在头文件中是一种非常不好的做法,因为它会阻止使用该头文件的任何人使用本地名称,否则该名称将是有效的。它基本上击败了命名空间的全部问题。
安迪·邓特


-5

您可以使用的替代方法很有限

标头:

class std_int_vector;

class A{
    std_int_vector* vector;
public:
    A();
    virtual ~A();
};

cpp:

#include "header.h"
#include <vector>
class std_int_vector: public std::vectror<int> {}

A::A() : vector(new std_int_vector()) {}
[...]

尚未在实际程序中进行测试,因此请期待它不是完美的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.