c++ - 在 main 之前将内容插入模板类的静态容器中

标签 c++ templates

我想构建一个仅包含静态数据成员和函数的模板类,基本上是带有一些内部数据的函数集合,我想填充代码的各个部分。我试图在到达 main() 之前将内容插入数据成员中。这对于非模板类来说效果很好,但对于模板类我似乎不知道如何让它工作。

代码如下:

#include <iostream>
#include <vector>

class Foo{
private:
    static std::vector<unsigned> content;
public:
    static void insert(unsigned u){ content.push_back(u); }
    static size_t size(){ return content.size(); }
};
std::vector<unsigned> Foo::content=std::vector<unsigned>();

struct Bar{ 
    Bar(){ Foo::insert(0);  }
} bar; 
// this works fine in gcc, but is this consistent or am I lucky?
// Foo::content will contain 0 prior to entering main

template <typename T>
class Quux{
private:
    static std::vector<T> content;
public:
    static void insert(T t){ content.push_back(t); }
    static size_t size(){ return content.size(); }
};
template <typename T>
std::vector<T> Quux<T>::content=std::vector<T>();

struct Wobble{ 
    Wobble(){ Quux<unsigned>::insert(0);    }
} wobble;  
// this does not work
// Quux<unsigned>::content will be empty prior to entering main

int main(){

    std::cout << Foo::size() << std::endl;  
    // outputs 1, as desired

    std::cout << Quux<unsigned>::size() << std::endl;   
    // outputs 0, makes me sad :(

    Wobble wobble2;
    std::cout << Quux<unsigned>::size() << std::endl;   
    // outputs 1, as desired
}

输出:

1
0
1

Foo是非模板类,我可以在 Foo::content 中插入内容运行之前main()通过结构Bar正好。我希望这是一贯的行为而不是我运气好?

当我尝试对模板类执行相同的操作时 Quux<T>不过,看来还得等到main()在我可以添加东西之前。有人可以解释为什么这是必要的以及(希望)解决这个问题的方法吗?我认为这与模板实例化的时间有关,但我无法弄清楚到底为什么。我期望 Quux<unsigned>在以下情况后完全可用:

struct Wobble{ 
    Wobble(){ Quux<unsigned>::insert(0); }
} wobble;  

我在这里缺少什么?为什么我可以在 main 之前向非模板化类添加内容通过bar但我不能通过 wobble 做同样的事情吗? ?有没有办法获得与Foo中相同的行为和Bar使用模板类?

最佳答案

[basic.start.init]/2

Definitions of explicitly specialized class template static data members have ordered initialization. Other class template static data members (i.e., implicitly or explicitly instantiated specializations) have unordered initialization. [...] Variables with ordered initialization defined within a single translation unit shall be initialized in the order of their definitions in the translation unit. [...] Otherwise, the unordered initialization of a variable is indeterminately sequenced with respect to every other dynamic initialization.

据我了解,您有未定义的行为,如 Quux<unsigned>::content 的初始化与 wobble 的初始化不确定地排序:

[介绍.执行]/13

Evaluations A and B are indeterminately sequenced when either A is sequenced before B or B is sequenced before A, but it is unspecified which.

也就是说,您的程序有可能访问未动态初始化的 Quux<unsigned>::content .

显式特化解决了问题。


请注意,在任何动态初始化之前,都会发生零初始化。因此,可以使用指针和动态内存分配来克服初始化顺序的问题:

template <typename T>
class Quux{
private:
    static std::vector<T>* content;
    static void create() { if(!content) content = new std::vector<T>; };
public:
    static void insert(T t){ create(); content->push_back(t); }
    static size_t size(){ create(); return content->size(); }
};
template <typename T>
std::vector<T>* Quux<T>::content;

这会在程序结束时引入“内存泄漏”;如果这是一个问题,您可以添加一个删除器对象,即删除 content 的另一个静态数据成员自行销毁(半个 RAII)。

关于c++ - 在 main 之前将内容插入模板类的静态容器中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17443163/

相关文章:

templates - 如何获得网站切换器而不是商店切换器?

c++ - 模板循环需要 const 值

php - 有什么好的方法可以将后台代码与 HTML 显示代码分开?

c++ - 读取 c++ istream 直到 EOF,同时丢弃内容

c++ - 什么是未知大小的 make_shared?

c++ - Boost.MPL 随状态变换?

C++ 模板滥用问题——使用附加类型信息增加 float

c++ - 函数对象与函数指针

c++ - Malloc 在 main() 或任何其他函数之外(即在全局范围内)

c++ - constexpr 函数中的非 constexpr 调用