c++方法的配置没有宏
C++ approach to configuration without macro
我正在实现一个库,并使用抽象类/接口,其中有一些不同的实现。我想让用户选择特定的实现使用配置文件,如config.h
。我有两个问题:
- 如何在没有宏的情况下实现这一点?
- 我使用继承来实现子类,但我不想在运行时动态选择类,我们仍然可以实现这一点吗?
我正在寻找c++11的解决方案,但c++14和c++17也是受欢迎的。
例如:
#include "config.h"
class library1_base {
virtual void blah() = 0;
virtual void bleh() = 0;
}
#ifdef LIB1_USE_IMPL1
class impl1_lib1 : library1_base { ... };
using library1 = impl1_lib;
#else
class impl2_lib1 : library1_base { ... };
using library1 = impl2_lib;
#endif
class library2_base {
virtual void ah() = 0;
virtual void oh() = 0;
}
#ifdef LIB2_USE_IMPL1
class impl1_lib2 : library2_base { ... };
using library2 = impl1_lib2;
#else
class impl2_lib2 : library2_base { ... };
using library2 = impl2_lib2;
#endif
config.h
如下(使用宏)
#define LIB1_USE_IMPL1
#define LIB2_USE_IMPL2
如何使用:
library1 x; // now this library1 should be using impl1_lib1
x.blah();
x.bleh();
library2 y; // now this library2 should be using impl2_lib2
y.ah();
y.oh();
首先,问自己"我该如何选择config,为什么?"
宏无处不在(您可以将它们定义为编译器标志,也可以在代码中定义),但它们缺乏作用域功能(它们是全局的,例如,不能定义为名称空间局部的),因此它们容易发生名称冲突。
如果你关心的是后者,你可以用typedefs/constants定义一个特殊的配置类,如下所示:
namespace myapp {
struct Config {
class library : library_base { ... }
using other_library = some_other_library;
using version_t = int;
static const version_t VERSION = 1;
}
}
但是要选择所需的配置,您必须包含多个configXXX.h文件中的一个,或者创建配置类模板并为每个配置设置多个专门化,如下所示:
enum class ConfigType {
JPEG, PNG
};
template <ConfigType type> struct Configs;
template <> struct Configs<ConfigType::JPEG> {
using library = libjpeg;
};
template <> struct Configs<ConfigType::PNG> {
using library = libpng;
};
...
static const ConfigType CONFIG_TYPE = ConfigType::JPEG;
...
using Config = Configs<CONFIG_TYPE>;
using library = Config::library;
更新#1:在后面的例子中,组合似乎是最好的解决方案(我已经重命名了东西,所以他们更有意义):
// configs.hpp
enum class AudioType {
MP3, OGG
};
template <AudioType type> struct AudioConfigs;
template <> struct AudioConfigs<AudioType::MP3> {
using Library = libmp3; // of course, you can define class in-place instead of typedef
};
template <> struct AudioConfigs<AudioType::OGG> {
using Library = libvorbis;
};
enum class ImageType {
JPEG, PNG
};
template <ImageType type> struct ImageConfigs;
template <> struct ImageConfigs<ImageType::JPEG> {
using Library = libjpeg;
};
template <> struct ImageConfigs<ImageType::PNG> {
using Library = pnglib;
};
template <AudioType audiotype, ImageType imagetype> struct Configs {
using AudioLibrary = typename AudioConfigs<audiotype>::Library;
using ImageLibrary = typename ImageConfigs<imagetype>::Library;
};
// config_setup.hpp - this one you will edit
#include "configs.hpp"
using Config = Configs<AudioType::MP3, ImageType::JPEG>;
// config.hpp
#include "config_setup.hpp"
using AudioLibrary = typename Config::AudioLibrary;
using ImageLibrary = typename Config::ImageLibrary;
// real code
#include "config.hpp"
AudioLibrary audioLibrary;
audioLibrary.doStuff();
替代结构:template <AudioType audiotype, ImageType imagetype> struct Configs {
using Audio = typename AudioConfigs<audiotype>;
using Image = typename ImageConfigs<imagetype>;
};
// Options should be accessed like Config::Audio::Library now
更新#2:(只是为了说明无尽的可能性)使用一些可变模板魔法,您可以缩短AudioConfigs/ImageConfigs/等。:
template <AudioConfig config> struct AudioConfigs : public LibraryConfigs<AudioConfig, config, AudioType::MP3, AudioType::OGG, libmp3, libvorbis> { };
…完全避免了带有多个专门化的样板代码。
相关文章:
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 一种在C++中读取TXT配置文件的简单方法
- 更改命令行 qt5 源代码构建配置的正确/快速方法
- 在调试配置中仅优化单个方法
- 修复警告"field a is not used"如果字段在配置中未使用的好方法
- 使用多个库时,在 CMakeList 中配置target_link_libraries的正确方法是什么?获取无法指定链接
- 设计方法以读/编写同一配置文件的不同版本
- 将配置文件存储在C 中的可执行文件中的方法
- POCO - 属性文件配置保存方法始终使用 ":" 作为分隔符进行写入
- 用Xcode 4配置谷歌测试的正确方法是什么
- 将clang++配置为在Cygwin中使用g++/gccSTL标头的最简单方法
- 读取配置属性的简单方法
- 设置"深度"配置选项的最佳方法是什么?
- c++方法的配置没有宏
- 在c++中,检查给定用户配置文件是否处于活动状态或已删除的最佳方法是什么?
- 跨平台访问配置目录的方法
- 配置c++应用程序构建的简单方法
- 在实现程序的配置设置时,什么是好方法
- 配置/首选项处理的推荐方法
- 有什么方法可以配置waf来在MAC系统中构建c++程序吗?