为模板化类模拟静态构造函数 [英] Emulating static constructors for templated classes

查看:49
本文介绍了为模板化类模拟静态构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要一个带有静态数据成员的模板化类,并通过模拟静态构造函数"对其进行初始化.对于非模板类,这已经得到回答(请参见静态构造函数?).但是,所有答案似乎都不适用于模板化类.

I would like to have a templated class with a static data member, and initialize it by emulating a "static constructor." For a non-templated class, this has already been answered (see static constructors in C++? I need to initialize private static objects and What is a static constructor?). However, none of the answers seem to work for a templated class.

下面是一个示例,该示例尝试将先前答案中的静态构造函数"惯用语改编为模板化类.(请注意,该示例只是初始化 int ,并且可以在没有此类构造函数的情况下编写;但是,我需要一个通用的解决方案.)

The following is an example that tries to adapt the "static constructor" idiom from the previous answers to a templated class. (Note that the example is simply initializing an int and could be written without such constructors; however, I require a general solution.)

#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

这是静态初始化顺序惨败"的示例吗?

Is this an example of the "static initialization order fiasco?"

推荐答案

我找到了适用于任何数据类型的干净解决方案.由于当编译器遇到特定的 Bar< N> :: x 进行实例化时,会评估 template 内的赋值操作,因此我们可以编写:

I have found a clean solution that works for any data type. Since the assignment operation inside a template is evaluated when the compiler comes across a specific Bar<N>::x to instantiate, we can write:

template<int N>
int Bar<N>::x = init<N>();

其中 init()是在 N 上模板化的函数,该函数返回 int .另外,对于编译器实例化的每个 N 值, init()只会被调用一次.

where init() is a function templated on N that returns an int. Additionally, init() will only be called once for each value of N that the compiler instantiates.

作为一个更有用的示例,在这里我根据一些任意函数初始化一个静态 std :: array :

As a more useful example, here I initialize a static std::array according to some arbitrary function:

#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;
}

这篇关于为模板化类模拟静态构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆