[c ++运行时分派2组静态常量

问题描述 投票:0回答:1

动机

CLI应用程序尝试使用box drawing characters。但是,根据标准输出设备,这可能不合适,因此有一个-t选项可以使用纯ASCII文本。

该概念只是一个示例,它适用于我们希望在运行时从两组或更多组静态常量中进行选择的任何地方。

问题是什么是干净利落的合理c ++技术。

所需用法语法

这仅是指示性的,但常量“调用”应该简洁

int main(int argc, char* argv[]) {

  // using derived class style here, but anything would do
  auto t = std::strcmp(argv[1], "-t") == 0 ? TxtTerminal() : BdTerminal();

  // here we want the syntax to be short
  std::cout << "text" << t.horiz << t.right_t << '\n';

}

已经尝试过

我尝试了基类和派生类样式(如上所述),但是有问题。我不能在TxtTerminal中放置一组常量,而在BdTerminal中扩展一组常量(扩展TxtTerminal)。

  • 使用静态常量不起作用,因为C ++不支持“后期静态绑定”,所以它总是使用具有实例的任何类的常量。
  • 使用这些类的成员变量和适当的实例(如上所示)不起作用(很好),因为派生类无法直接初始化基类成员。...
  • 也不通过其构造函数初始化程序列表...
  • 派生类必须将整个集合传递给基类构造函数,然后该基类构造函数修改已经(BaseClass)初始化的值。真是尴尬而long绕。我想传递一些struct config { .. };可能有效
  • 类似地使用单个类,将两组常量都放在其中map<key,config>中,并使用吸气剂通过构造函数初始化的bool textmode成员状态变量来检索适当的常量。
  • 也许使用带有某些模板参数的模板化解决方案?好吧,不,因为这是一个运行时开关。
  • 类似于模板的想法是对2个独立的常量名称空间使用using别名的某种解决方案。相同的问题。编译时间。而不是运行时。
  • 使用variable templates有点像new c++20 maths constants。同样的问题,不是运行时。

[当然,所有这些const,即“盒式绘图终端”的控制字符的字符串都只是一个字节长。理想情况下,将它们压缩为可执行文件的const char*(linux)段中的文字初始化的.textstd::string似乎有些过分)。无论我们在何处编写这些常量,我们都希望轻松concatenation以使代码易于读取和维护。使用const char*字符串文字不是那么容易吗?

[许多选项,似乎没有一个很好。我是否缺少明显的东西?

c++ static runtime constants dispatch
1个回答
1
投票

从评论中,我发现您正在寻找的是:

class Base {
    virtual const char* get_config() = 0;

public:
    const char* config;
    /* other members */

    Base(/*arguments*/) : config(get_config()), /*other initializers*/ { }

    virtual ~Base() = default;

    // methods can use `config` here as pointer
};

struct Derived1 : Base {
    using Base::Base;
    const char* get_config() override {
        static const char[] config{/*...*/};
        return config;
    }
};

struct Derived2 : Base {
    using Base::Base;
    const char* get_config() override {
        static const char[] config{/*...*/};
        return config;
    }
};

现在就可以使用派生类型,就像它们的构造函数定义为在Base中一样,并且所有类中的方法都可以使用config作为指针,而不会产生任何问题或虚拟调用开销。


或者,如果您想在两种情况之间进行全局切换(即,这些对象的多个实例没有使用不同的配置),那么就根本不需要继承。只需定义一个静态指针,然后让它在两者之间切换即可:

struct Terminal {

    static const char config1[]{/*...*/};
    static const char config2[]{/*...*/};

    static const char* config{};

    static void chooseConfig(/*parameters*/) {
        config = /*condition*/ ? config1 : config2;
    };

    // use `config` everywhere

};

int main(int argc, char* argv[]) {

    Terminal::chooseConfig(/*arguments*/);

    //...
}
© www.soinside.com 2019 - 2024. All rights reserved.