我花了一些时间来检查boost::库架构,并对以下事实感兴趣:
在库的某些部分中,使用的yyy_fwd.hpp想法很常见(参见boost/detail或boost/flyweight示例).
这些文件显然只包含一些基于模板的类的前向声明,据我所知,可以在编译时间方面受益.
有人可以指出它们在什么情况下有所帮助,我应该在设计自己的模板时使用相同的想法吗?
谢谢.
标准库包括一个<iosfwd>头,(forward)声明所有流,包括任何typedefs,并定义char_traits模板,包括特化.
遗憾的是,不存在这样<stlfwd>的是(正向)宣布所有常见的STL的数据类型和功能,如头vector,map,less,sort等.甚至更不幸的是,用户代码不允许这种声明/添加typedefs到的std名称空间,如每
§17.4.3.1 [lib.reserved.names] p1:
除非另有说明,否则C++程序未定义向命名空间内的命名空间或命名空间添加声明或定义.程序可以将任何标准库模板的模板特化添加到命名空间.
stdstdstd
是的,它涵盖(前向)声明的情况,即使标准库中已存在类型.当然,即使添加了这样的声明,大多数(所有?)编译器也会表现得非常正常,但严格来说,语言律师说,这是未定义的行为.我觉得这typedef对标准容器来说特别乏味,比如:
// how to forward declare map and string?
typedef std::map<std::string, std::string> Attributes;
Run Code Online (Sandbox Code Playgroud)
现在,这可以被视为缺陷吗?
我的意思是不存在<stlfwd>标题(或者更好<stdfwd>,也包括覆盖<iosfwd>)和标准库中已经存在的声明禁令.
此外,根据这个问题,如果一个(转发)完全按照标准的要求声明标准容器,算法和仿函数/函数,那么代码应该是完全有效的(如果不是禁止用户自己的声明)该std命名空间),因为实现是不允许添加任何隐藏/默认的模板参数.
我问这个是因为我想最终提交一份有关此问题的缺陷报告.
我正在尝试为枚举使用正确的前向声明.因此,我搜索了互联网,但我找不到有用的东西.
我在标题中使用:
// Forward declaration
enum myEnumProcessState;
Run Code Online (Sandbox Code Playgroud)
然后我在结构中使用这个枚举:
struct myStruct {
[...]
myEnumProcessState osState;
[...]
};
Run Code Online (Sandbox Code Playgroud)
在另一个标题中:
enum myEnumProcessState {
eNotRunning,
eRunning
};
Run Code Online (Sandbox Code Playgroud)
我发现这个类型应该放在enum forward声明中才能被接受.但是,我不知道我应该为流程状态添加哪种"类型".这些不起作用:
enum myEnumProcessState : unsigned int;
enum myEnumProcessState : String;
Run Code Online (Sandbox Code Playgroud)
我想跳过前方声明,但我的结构正在哭,因为它再也找不到它了......
所以我有点困惑.你知道解决方案吗?
非常感谢 :)
我正在尝试重构我的代码,以便我使用前向声明而不是包含大量的标头.我是新手,对boost :: shared_ptr有疑问.
说我有以下界面:
#ifndef I_STARTER_H_
#define I_STARTER_H_
#include <boost/shared_ptr.hpp>
class IStarter
{
public:
virtual ~IStarter() {};
virtual operator()() = 0;
};
typedef boost::shared_ptr<IStarter> IStarterPtr;
#endif
Run Code Online (Sandbox Code Playgroud)
然后我在另一个类中有一个函数,它将一个IStarterPtr对象作为参数,比如说:
virtual void addStarter(IStarterPtr starter)
{
_starter = starter;
}
...
IStarterPtr _starter;
Run Code Online (Sandbox Code Playgroud)
如何在不包含IStarter.h的情况下转发声明IStarterPtr?
我正在使用C++ 98,如果这是相关的.
假设我有2个班:
class A
{
public:
typedef std::shared_ptr<A> Ref;
...
private:
B::Ref _b;
}
class B
{
public:
typedef std::shared_ptr<B> Ref;
...
private:
A::Ref _a;
}
Run Code Online (Sandbox Code Playgroud)
这显然需要B类和B :: Ref的前向声明.前向声明B很简单,但如何对B :: Ref也这样做?
考虑这个代码,有一个明显的编译错误:(1)
struct A;
struct B {
B() { new A(); } // error: allocation of incomplete type 'A'
};
Run Code Online (Sandbox Code Playgroud)
使用a unique_ptr也无济于事:(2)
struct A;
struct B {
B() { std::make_unique<A>(); } // error: due to ~unique_ptr()
};
Run Code Online (Sandbox Code Playgroud)
然后(令我惊讶的是)我发现,这将编译:(3)
struct A;
struct B {
B() { std::make_unique<A>(); }
};
struct A {}; // OK, when a definition is added **below**
Run Code Online (Sandbox Code Playgroud)
然后我检查了,这是否有帮助new- 不:(4)
struct A;
struct B {
B() { new A(); } // error: allocation of …Run Code Online (Sandbox Code Playgroud) 以下代码似乎在Clang ++和GCC上正常工作:
#include <vector>
class A {
private:
int i;
std::vector<A> children;
public:
A& add();
};
A& A::add() { children.emplace_back(); return children.back(); }
int main() {
A a;
A& a2 = a.add();
}
Run Code Online (Sandbox Code Playgroud)
std::vector<A>声明数据成员时,A仍然是不完整的类型.同样在使用std::vector<B>和B只向前声明class B;.它应该工作,std::vector因为它只包含一个指针A.
这是保证工作还是未定义的行为?
我现在通过Zed A. Shaw的"学习C艰难之路"学习C编程.有这个代码(取自他的网站):
#include <stdio.h>
#include <ctype.h>
// forward declarations
int can_print_it(char ch);
void print_letters(char arg[]);
void print_arguments(int argc, char *argv[])
{
int i = 0;
for(i = 0; i < argc; i++) {
print_letters(argv[i]);
}
}
void print_letters(char arg[])
{
int i = 0;
for(i = 0; arg[i] != '\0'; i++) {
char ch = arg[i];
if(can_print_it(ch)) {
printf("'%c' == %d ", ch, ch);
}
}
printf("\n");
}
int can_print_it(char ch)
{
return isalpha(ch) || isblank(ch);
}
int main(int …Run Code Online (Sandbox Code Playgroud) 例:
class A
{
class B
{
A c;//error!A is an incomplete type
void test() { A b;/*OK,but why?*/ }
};
};
Run Code Online (Sandbox Code Playgroud)
代码片段对我来说似乎很奇怪,这两种用法有A什么区别?
我有test.h一个包含类的.h文件.在这个类中有一个私有方法返回一个我不想做"公共"的类型的指针,但我希望能够将此test.h文件包含在其他源文件中.
通常,在.h文件中使用前向声明很容易:
class Foo;
Run Code Online (Sandbox Code Playgroud)
但问题是这种类型来自一个我无法改变的C文件(因为它是我不维护的其他代码)而且它是一个typedef.
基本上我的意思test.cpp是:
// this type comes from a C file, cannot be changed to struct or class
typedef struct
{
int x;
} Foo;
#include "test.h"
static Foo foo;
Foo *Test::private_function()
{
foo.x = 12;
return &foo;
}
int Test::compute()
{
auto *local_foo = private_function();
return local_foo->x;
}
Run Code Online (Sandbox Code Playgroud)
我的test.h文件是:
#pragma once
struct Foo;
class Test
{
public:
Test() {}
int compute();
private:
Foo *private_function(); …Run Code Online (Sandbox Code Playgroud)