我有几个独立编写的翻译单位;为了便于讨论,每个都有一个(静态或外部)全局std :: string变量。这些字符串可能具有不同的名称,与TU的名称无关。并且我不保证编译的TU在与具有main.cpp
功能的TU(例如,magic1.h
)链接之前才会联系。它们都包含相同的标题fun_strings
,它定义了一个名为#include <string>
#include "magic1.h"
int main() {
// magic2
for(const std::string& s : fun_strings) {
foo(s);
}
}
的全局变量,我们将在稍后选择它的类型。
现在,我希望能够做到以下几点:
main.cpp
关键在于即使foo.cpp
_doesn't_include_any_of_the_other_TUs_,它们也有一些静态代码,这会导致fun_strings拥有所有TU各个字符串的副本/引用/指针。
当然,问题是如何实现这一目标。我将“magic1”和“magic2”表示为可以放置常用代码的地方。对于带有字符串的示例TU,请在std::string just_a_string("I'm a foo fun string");
中使用{{1}}。
备注:
答案 0 :(得分:2)
如何创建一个在声明字符串时自动将字符串添加到fun_strings
的类:
class fun_string
{
public:
fun_string(const char * string)
: m_string(string)
{
get_fun_strings().push_back(m_string);
}
private:
string m_string;
};
在翻译单元中,您将使用fun_string
定义全局字符串。
在上面的代码中,我直接使用了get_fun_strings()
而不是全局名为fun_strings
的代码。这是为了避免在初始化另一个静态变量时使用静态变量时可能出现的任何static initialisation fiasco问题。
vector<string> & get_fun_strings()
{
static vector<string> v;
return v;
}
请注意,从C ++ 11开始,本地函数静态保证以线程安全的方式初始化。这可能不是一个问题,因为如果你有至少一个全局fun_string
,函数local static将在main()
之前初始化,因此可能在创建任何其他线程之前。
至于忽略冲突要求 - 这可以在fun_string
构造函数内完成。也就是说你应该在插入之前检查碰撞并适当地处理这种情况。
以下是此方法的live demo。
有几点需要注意:
get_fun_strings()
返回的向量包含main()
之前的所有字符串。get_fun_strings()
。请参阅有关静态初始化顺序的页面,了解其原因以及如何更改它以支持此类用法。