我们有一个相当大的项目,在几个地方定义static const std::string
作为参数名称;其中一些需要在静态初始化期间连接:
foo.h中:
struct Foo {
static const std::string ParamSuffix;
};
Foo.cpp中:
const std::string Foo::ParamSuffix = ".suffix";
bar.h:
struct Bar {
static const std::string ParamPrefix;
};
bar.cpp:
const std::string Bar::ParamPrefix = "prefix";
baz.h:
struct Baz {
static const std::string ParamName;
};
baz.cpp:
const std::string Baz::ParamName = Bar::ParamPrefix + Foo::ParamSuffix;
问题显然是“静态初始化惨败”,因为未定义static const
成员的初始化顺序。
我不喜欢通常的解决方案,即用函数替换所有这些变量,因为
我目前无法使用C ++ 11,这会使constexpr
功能更加简单(我认为)。
问题是:是否有任何技巧可以让我连接static const std::string
(或包装对象或其他)以初始化另一个static const std::string
?
答案 0 :(得分:4)
问题是:是否有任何技巧可以让我连接静态const std :: strings(或包装器对象或其他)来初始化另一个静态const std :: string?
除了你不喜欢的那个之外,不是一件简单的事情:为静态字符串创建函数。
虽然有一些非平凡的替代方案(例如,用字符串容器/字符串映射替换所有硬编码字符串并在应用程序启动时加载映射)。
我的建议是使用静态功能(你拒绝的解决方案)。
答案 1 :(得分:2)
为什么你认为std::string const
有什么特别之处? (提示:它不是)即使您可以使用C ++ 11的constexpr
它也无济于事,因为您无法使std:string
成为常量表达式(它们可能需要分配内存,而不是'一个可行的常数表达式)。您可以处理用于constexpr
的类似字符串的类,可以将其转换为std::string
,但我不确定是否可以将它们连接起来以生成新的constexpr
。< / p>
您可能要做的是提取您需要使用的字符串作为连接的一部分,并提供它们作为宏的值。字符串文字(适用于char const[N]
的类型为N
)可以通过简单地将它们放在一起来连接起来:
// foo.h
#define FOO_PARAM_SUFFIX ".suffix"
struct Foo {
static const std::string ParamSuffix;
};
// foo.cpp:
std::string const Foo::ParamSuffix(FOO_PARAM_SUFFIX);
// bar.h:
#define BAR_PARAM_SUFFIX "prefix"
struct Bar {
static std::string const ParamPrefix;
};
// bar.cpp:
std::string const Bar::ParamPrefix(BAR_PARAM_SUFFIX);
// baz.h:
#include "foo.h"
#include "bar.h"
#define BAZ_PARAM_NAME BAR_PARAM_PREFIX FOO_PARAM_SUFFIX
struct Baz {
static std::string const ParamName;
};
// baz.cpp:
#include "foo.h"
#include "bar.h"
std::string const Baz::ParamName(BAR_PARAM_PREFIX FOO_PARAM_SUFFIX);
我猜想BAZ_PARAM_NAME
没有在其他地方使用,在这种情况下它也不必定义:它被定义只是为了表明它可以完成。 Bar::ParamName
的初始化假定BAZ_PARAM_NAME
未定义。
答案 2 :(得分:2)
当文本不依赖于另一个变量时,您可以考虑将类型从const std::string
更改为const char
数组ala const char param_prefix[] = "prefix";
- 可能会减少对客户端使用的强制更改,但这可能会隐藏每次使用时必须(或无意中)创建的新临时std::string
。
检查你的系统,但你几乎可以肯定在构造其他const char
常量时安全地使用这些std::string
变量 - 但你不幸的是 - std::string
依赖于其他std::string
s。
如果要将现有值解释为可能的const
- char
和std::string
仅仅取决于const
- char
太难了s,或者只是没有覆盖足够的情况,那么对每一个常数的批量修改都值得追求。
包装器的吸引力在于您可以保持使用的类型和语义相同。为此,您需要使用自己的类型替换所有这些运行时初始化的字符串,这些类型可以协调两个中心列表: - 初始化对象和等待对象。观察者模式是合适的,或者你可以例如注册回调列表并通过循环main()
调用它们直到它们都表示成功来完成初始化:如果已知对象初始化中的至少一些是静态的,则可以允许一个对象测试另一个对象的初始化状态,将避免必须让构造函数注册完成。
如果可以借助更智能的源代码修改工具(例如awk)进行操作 - 最好只更改常量以便函数干净地返回。