C++ 如何在c++;,比如std::string?

C++ 如何在c++;,比如std::string?,c++,C++,可能的重复项: 我想转发declare std::string,顺便问一下,我可以转发声明一个结构吗?一般来说,为了转发声明命名空间的类,您可以这样做: namespace MyOtherNamespace { class MyForwardedClass; } namespace MyNamespace { MyOtherNamespace::MyForwardedClass * pClass; } 但是我怀疑关于std::可能有一些限制,不过我不确定,我要检查一下。因

可能的重复项:


我想转发declare std::string,顺便问一下,我可以转发声明一个结构吗?

一般来说,为了转发声明命名空间的类,您可以这样做:

namespace MyOtherNamespace
{
    class MyForwardedClass;
}

namespace MyNamespace
{
    MyOtherNamespace::MyForwardedClass * pClass;
}

但是我怀疑关于
std::
可能有一些限制,不过我不确定,我要检查一下。因为我记得有一些由于typedef引起的冲突…

std::string是一个typedef,所以不能直接向前声明它。您可以查找确切的声明,向前声明并自己定义typedef,但是您还必须向前声明char_traits和分配器。所以这可能会起作用,尽管它不应该起作用*:

namespace std
{
  template< class T, class Traits, class Allocator >
  class basic_string;

  template< class T >
  struct char_traits;

  template< class T >
  class allocator;

  typedef basic_string< char, char_traits< char >, allocator< char > > string;
}
名称空间std
{
模板
类基本字符串;
模板
结构特征;
模板
类分配器;
typedef basic_string,分配器>字符串;
}
但最终你可能会更好地包括。我也不确定这些声明是否在所有平台上都完全相同,更不用说如果字符串头中的声明发生变化会导致什么问题了


*请参阅下面的评论,简单回答:不要这样做。永远不要试图从标准库(或boost或cgal等)中“向前声明”元素。。。你会踩到自己的脚。上面的文章已经声明,您需要向前声明完整的类型定义。这很容易导致在其他平台或标准库的不同实现上发生冲突

<>这是一个传统的C++问题。std或boost的未反射包含会导致不可接受的编译时间、模板实例化错误的大量传播等等。我最近在我们的一个项目中看到过这种情况,在这个项目中,没有任何线索的人都在工作。您有几个选择可以避免或隐藏依赖项:

  • 不要在API中公开这些元素,请使用(const)char*,例如
  • 编写泛型代码,现在不需要使用运行时类型
  • 编写接口,封装这些元素的功能,并允许您将依赖项移动到源文件中

  • 最好的变体将使用这三者的组合。

    为什么需要向前声明而不是
    #include
    ?未定义的行为:除了用户定义类型的标准函数模板的专门化之外,不允许在
    std
    中放置定义或声明。即使您的定义与实现的定义相匹配,标准也会说行为是未定义的。所以我会说,“将在大多数实现上工作”或者“将在X、Y和Z上工作”,而不是“应该工作”。关于这件事没有“应该”,除了你“不应该”做之外;-)查了一下,你说得对。在这个问题上,哪些编译器遵循标准?@stijn:嗯,它们都遵循标准。因为该标准规定,执行此操作的程序具有“未定义的行为”(而不是将其定义为语言约束),所以允许实现执行任何操作,包括执行您希望发生的事情。我没有看到编译器发布诊断,他们不需要这样做,但这是一种很好的方式来提醒那些在没有看到标准的那一部分的情况下尝试诊断的人。我想这是因为标题可以与编译器分开提供(例如,Dinkumware、STLPort),而不会生成警告。@Steve请您指出标准的相关章节好吗?找不到……我只是想知道“未定义的行为”。从技术上讲,与实现不兼容的类型或签名的转发声明行为不应导致“未定义行为”。转发声明匹配,程序编译并链接,或者存在冲突,这些冲突必须生成编译时或链接时错误。这与所使用的名称空间无关。仍在等待指向标准相关部分的指针。不管怎样,有一些例子是明智的,考虑STD::Tr1实现与Boost交付。