gpt4 book ai didi

c++ - 如何避免公共(public)头文件中#define 的编译时间过长

转载 作者:可可西里 更新时间:2023-11-01 18:39:06 25 4
gpt4 key购买 nike

我想知道是否有一种优雅的方法可以解决这个问题。假设有一个共同的标题,例如

// common.h
#ifndef COMMON_H
#define COMMON_H

#define ENABLE_SOMETHING
//#define ENABLE_SOMETHING_ELSE
#define ENABLE_WHATEVER
// many others

#endif

现在这个文件包含在,比方说 100 个其他头文件和各种 #define 用于启用或禁用代码的某些部分,这些部分仅限于 1-2 个文件。

每次更改单个 #define 时,整个项目似乎都在重建(我正在使用 Xcode 5.1),这是有道理的,因为它必须围绕代码和编译器逐字替换无法先验地知道它在哪里使用。

我正试图找到一种更好的方法来管理它,以避免编译时间过长,因为这些定义确实更改了很多次。将每个定义拆分到相应的文件中可能是一个解决方案,但我想要将所有内容打包在一起的实用方法。

所以我想知道是否有一种通常用于解决这个问题的模式,我在考虑有

// common.h
class Enables
{
static const bool feature;
};

// common..cpp
bool Enables::feature = false;

编译优化二进制文件时,这在语义上是否等价? (例如,false 启用中的代码将完全消失)。

最佳答案

这里有两个明显的问题:

Splitting each define in their corresponding file/files could be a solution but I'd like the practical way to have everything packed together.

这是您的第一个问题。如果我理解正确,如果您有多个功能区域,那么您不必为每个功能区域都包含一个标题(但所有内容都包含一个标题)不感兴趣。

应用这些步骤:

  • 按功能将代码拆分到不同的 header 中;每个 header 应(最多)包含由单个 #define FEATURESET 启用的内容(并且完全不知道 FEATURESET 宏的存在)。

  • 确保每个头文件只编译一次(在每个功能头文件的开头添加#pragma once)

  • 添加一个方便的头文件,根据您定义的功能执行 #if#ifdef,并根据需要包含功能文件:

    // parsers.h
    // this shouldn't be here: #pragma once

    #ifdef PARSEQUUX_SAFE
    #include <QuuxSafe.h>
    #elif defined PARSEQUUX_FAST
    #include <QuuxFast.h>
    #else
    #include <QuuxSafe.h>
    #endif

    // eventually configure static/global class factory here
    // see explanation below for mentions of class factory

客户端代码:

#include <parsers.h> // use default Quux parser

#define PARSEQUUX_SAFE
#include <parsers.h> // use safe (but slower) Quux parser

So I was wondering if there is a pattern which is usually used to solve this problem

这是你的第二个问题。

在 C++ 中按特性启用功能的规范方法是根据基类、类工厂和通用接口(interface)编程来定义特性 API。

// common.h
#pragma once
#include <Quux.h> // base Quux class

struct QuuxFactory
{
enum QuuxType { Simple, Feathered };
static std::unique_ptr<Quux> CreateQuux(int arg);

static QuuxType type;
};

// common.cpp:

#include <common.h>
#include <SimpleQuux.h> // SimpleQuux: public Quux
#include <FeatheredQuux.h> // FeatheredQuux: public Quux

std::unique_ptr<Quux> QuuxFactory::CreateQuux(int arg)
{
switch(type) {
case Simple:
return std::unique_ptr<Quux>{new SimpleQuux{arg}};
case Feathered:
return std::unique_ptr<Quux>{new FeatheredQuux{arg}};
};
// TODO: handle errors
}

客户端代码:

// configure behavior:
QuuxFactory::type = QuuxFactory::FeatheredQuux;

// ...

auto quux = QuuxFactory::CreateQuux(10); // creates a FeatheredQuux in this case

这样做有以下优点:

  • 它很简单,不使用宏

  • 可重复使用

  • 它提供了足够的抽象级别

  • 它不使用宏(如“完全”)

  • 假设的 Quux 功能的实际实现仅包含在一个文件中(作为实现细节,仅编译一次)。您可以在任何需要的地方包含 common.h,它根本不会包含 SimpleQuux.h 和 FeatheredQuux.h。

作为一般准则,您应该编写代码,使其不需要宏即可运行。如果这样做,您会发现要在其上添加的任何宏都是微不足道的。相反,如果您从一开始就依赖宏来定义您的 API,那么如果没有它们,代码将无法使用(或接近无法使用)。

关于c++ - 如何避免公共(public)头文件中#define 的编译时间过长,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24185462/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com