【问题标题】:How to forward declare a template class in namespace std?如何在命名空间std中转发声明模板类?
【发布时间】:2011-04-22 04:55:34
【问题描述】:
#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(我认为是分配器)有更多的模板参数。但是,这不是重点。我是否必须知道模板类的完整模板声明才能转发声明它?

编辑:我之前没有使用指针 - 它是一个参考。我用指针试试看。

【问题讨论】:

  • 而在list的情况下,第二个参数是默认参数std::allocator&lt;T&gt;
  • 人们可能会认为 STL 不包含前向声明标头是一种疏忽。另一方面,它的文件经常被包含在内,它可能不会对编译时间产生任何好处......
  • __TEST__ 是保留标识符,don't use it

标签: c++ templates g++


【解决方案1】:

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

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

但是,即使在 namespace std 中做出这样的前向声明,标准也明确禁止:只有您可以在 std 中放入的东西是模板专业化,通常std::less 在用户定义的类型上。如有必要,其他人可以引用相关文字。

只需#include &lt;list&gt;,别担心。

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

【讨论】:

  • 为什么禁止在namespace std btw 转发声明东西?
  • 查看这个答案 (stackoverflow.com/questions/307343/…) 和链接的新闻组讨论。
  • Jon / Nakiya,为什么不使用#pragma once 而不是#ifdef。现在大多数编译器都支持它。
  • @Mark:因为它是#pragma,这就是原因。虽然这是一种选择。
  • 该问题有无数个重复项。只需搜索:stackoverflow.com/search?q=pragma+once
【解决方案2】:

我解决了这个问题。

我正在为 C++ (Eclipse Juno) 中的网络模拟实现一个 OSI 层(滑块窗口,第 2 级)。我有框架(模板&lt;class T&gt;)及其状态(状态模式、前向声明)。

解决方法如下:

*.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){

还有……另一个班级。

【讨论】:

  • 将任何using namespace 放在头文件中是一种非常糟糕的做法,因为它会阻止使用该头文件的任何人使用原本有效的本地名称。它基本上破坏了命名空间的全部意义。
【解决方案3】:

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

【讨论】:

    【解决方案4】:

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

    标题:

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

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

    【讨论】:

      猜你喜欢
      • 2011-03-17
      • 2013-09-30
      • 2023-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-30
      • 2021-02-12
      相关资源
      最近更新 更多