模拟模板类的静态构造函数
Emulating static constructors for templated classes
我想拥有一个带有静态数据成员的模板类,并通过模拟"静态构造函数"来初始化它。对于非训练类的类别,已经回答了这一点(请参阅C 中的静态构造函数?我需要初始化私有静态对象,什么是静态构造函数?)。但是,似乎没有任何答案适用于模板类别。
以下是一个示例,它试图从先前对模板类的答案中调整"静态构造"成语。(请注意,该示例只是初始化int
,并且可以在没有此类构造函数的情况下编写;但是,我需要一般的解决方案。)
#include <iostream>
struct Foo
{
static int x;
static struct init
{
init()
{
std::cout << "Initializing Foo..." << std::endl;
x = 1;
}
} initializer;
};
int Foo::x;
Foo::init Foo::initializer;
template<int N>
struct Bar
{
static int x;
static struct init
{
init()
{
std::cout << "Initializing Bar..." << std::endl;
x = N;
}
} initializer;
};
template<int N>
int Bar<N>::x;
template<int N>
typename Bar<N>::init Bar<N>::initializer;
int main()
{
std::cout << Foo::x << std::endl;
std::cout << Bar<1>::x << std::endl;
return 0;
}
此输出:
Initializing Foo...
1
0
但我希望它能输出:
Initializing Foo...
Initializing Bar...
1
1
这是"静态初始化顺序惨败?"
no,它是不是静态初始化顺序fiasco。这仅仅是由于模板类的每个成员都是模板本身的结果,因此直到使用后才实例化。
。您的代码永远不会使用init
成员,因此init
永远不会实例化。
但是,您的问题很容易解决:
#include <iostream>
template<int N>
struct Bar
{
static int x;
};
template<int N>
int Bar<N>::x= N;
int main()
{
std::cout << Bar<1>::x << std::endl;
return 0;
}
这为您提供了更简单的方式。
您需要解释实例化initializer
:
[...]
template<int N>
typename Bar<N>::init Bar<N>::initializer;
template
typename Bar<1>::init Bar<1>::initializer;
int main()
{
std::cout << Foo::x << std::endl;
std::cout << Bar<1>::x << std::endl;
return 0;
}
原因是Bar<1>::x
不取决于Bar<1>::initializer
。因此,由于您不使用它,编译器不会实例化。实际,initializer
初始化不会初始化x
。x
是第一个零初始化,则如果initializer
实例化,则x
为分配了一个新值。
只要initializer
与 x
是实例化在同一翻译单元中实例化,就没有静态初始化惨败的风险。因此,也可以解释 x
也是一个好主意。
另外,您可以将这些变量声明为静态当地人:
#include <iostream>
template<int N>
struct Bar
{
static int x()
{
static int x_val;
static struct init
{
init()
{
std::cout << "Initializing Bar..." << std::endl;
x_val = N;
}
} initializer;//indeed this circumvolution is no more needed.
return x_val;
}
};
int main(){
std::cout << Bar<1>::x() << std::endl;
}
但是,如果初始化不是微不足道的,则x()
内的生成代码可能正在优化。
根据您的问题,您还可以将X定义为INT周围的包装器:
class int_inited{
int val;
public:
int_inited(){
std::cout << "Perfoming initialization" << std::endl;
val=42;
}
operator int&(){
return val;
}
operator const int &() const{
return val;
}
};
template<class N>
struct Bar{
static int_inited x;
[...];
我找到了一个可用于任何数据类型的干净解决方案。由于当编译器遇到特定的Bar<N>::x
实例化时,评估了template
中的分配操作,因此我们可以写:
template<int N>
int Bar<N>::x = init<N>();
其中init()
是返回int
的N
上的函数。此外,init()
仅针对编译器实例化的N
的每个值调用一次。
作为一个更有用的例子,在这里我根据某些任意功能初始化静态std::array
:
#include <iostream>
#include <array>
template<int N>
struct Foo
{
static std::array<double,N> x;
};
template<int N>
std::array<double,N> init()
{
std::array<double,N> y;
for (int i=0; i<N; ++i) {
y[i] = (double)(i*i+i)/N;
}
return y;
}
template<int N>
std::array<double,N> Foo<N>::x = init<N>();
int main()
{
const int N = 10;
for (int i=0; i<N; ++i) {
std::cout << Foo<N>::x[i] << std::endl;
}
return 0;
}
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- enable_if转换构造函数(静态强制转换,is_base_of)
- 在作为静态成员包含在另一个类中的类的构造函数中使用 cout
- C++构造函数和静态成员
- 静态 std::map instatiation 在类的方法中调用构造函数吗?
- 错误: 无效使用非静态数据成员"应用程序::应用程序构造函数"
- 未调用的初始化静态thread_local结构的构造函数和析构函数
- 了解类构造函数的静态强制转换
- 静态类属性,C++中的多个构造函数
- 函数指针静态,构造函数
- 如何初始化堆,以便静态构造函数可以在常规 MFC dll 中使用堆?
- C++返回容器的静态构造函数
- 模拟模板类的静态构造函数
- c++中的静态构造函数和致命错误LNK1120:1个未解析的外部
- 访问std :: MAP中的静态构造函数New New拨号
- 静态构造函数的顺序与组合是否正确
- 在 c++ 中实现静态构造函数不起作用
- 是否可以使用静态构造函数初始化式
- 在我自己的操作系统内核上的c++静态构造函数
- 从静态构造函数代码调用pthread库时失败