如何在命名空间std中前向声明一个模板类?

133
#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
1
可能是C++前向声明问题的重复。 - iammilind
4个回答

147

问题不在于你无法前向声明模板类。是的,你需要知道所有模板参数及其默认值才能正确地进行前向声明:

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

但是在namespace std中甚至进行这样的前向声明都是被标准明确禁止的:你只能放置一个模板特化,通常是一个用户定义类型上的std::less。如果需要,其他人可以引用相关文本。

只需#include <list>,不必担心。

顺便提一下,任何包含双下划线的名称都保留供实现使用,因此您应该使用类似于TEST_H而不是__TEST__的名称。它不会生成警告或错误,但是如果您的程序与实现定义的标识符发生冲突,则不能保证正确编译或运行:它是不合法的。还禁止使用以下划线开头后跟大写字母的名称,等等。总之,除非您知道自己在处理什么魔术,否则不要以下划线开头。


4
namespace std 中为什么禁止使用前置声明呢? - nakiya
4
请查看此答案(https://dev59.com/dXVC5IYBdhLWcg3wZwNT#307408)以及链接的新闻组讨论。 - Jon Purdy
7
Jon / Nakiya,为什么不使用#pragma once而不是#ifdef呢?这个指令现在大多数编译器都支持。 - Mark Ingram
11
@Mark:因为这是“#pragma”,所以才这样。尽管它是一种选项。 - Jon Purdy
2
有大量重复的那个问题。只需搜索: http://stackoverflow.com/search?q=pragma+once - Jon Purdy
显示剩余5条评论

20

我解决了那个问题。

我正在用C ++(Eclipse Juno)实现一个网络模拟的OSI层(滑动窗口,第2级)。 我有帧(模板<class T>)及其状态(状态模式,前置声明)。

解决方案如下:

*.cpp文件中,必须包含您提前声明的头文件,即:

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;

}

这是C++代码:

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

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

还有...另一个类。


35
在头文件中使用任何using namespace都是非常糟糕的做法,因为它会阻止任何使用该头文件的人使用本地名称,否则这些名称将是有效的。这基本上背离了命名空间的整个目的。 - Andy Dent

10

前置声明应该指定完整的模板参数列表。


-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()) {}
[...]

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接