Emulating static constructors for templated classes

Dan Fortunato

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.

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

This outputs:

Initializing Foo...
1
0

But I expected it to output:

Initializing Foo...
Initializing Bar...
1
1

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

Dan Fortunato

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>();

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.

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

Este artículo se recopila de Internet, indique la fuente cuando se vuelva a imprimir.

En caso de infracción, por favor [email protected] Eliminar

Editado en
0

Déjame decir algunas palabras

0Comentarios
Iniciar sesiónRevisión de participación posterior

Artículos relacionados

static const int in CUDA for a templated code

Order of items in classes: Fields, Properties, Constructors, Methods

static constructors in C++? I need to initialize private static objects

ApplicationDbContext for static classes

How to allocate storage for a static const templated specialized integral value

Why do templated class data members require the static keyword?

Static variables in non-static inner classes

Lombok annotations for inner static classes

How are Classes and Function Constructors different from one another

Adding constructors and destructors in a UML class diagram for C++ classes

Why use a "tpp" file when implementing templated functions and classes defined in a header?

Emulating GCC Statement Expressions

Is it bad to have private static fields in Util classes?

When to use static vs instantiated classes

Creating static variables in classes (C++)

Creating static behavior that can be overridden in derived classes in C#

In which cases it makes sense to use factory classes instead of static functions?

Static classes/fields. How often are you using it?

Why can't the static and register storage classes be used together?

Get nested static classes names programatically and access a method

Converting UML to code c++. Problem with inheritence. Do constructors of all classes run when object of any one of them is created?

Emulating a do-while loop in Bash

Scanning without sequences in theano? (emulating range())

Inheriting constructors

Templated class syntax errors

"decay" a templated alias

Rcpp: Constructing templated functions

Запретить использование модификатора static

Javascript ES6 - Enums inside classes used outside like a static enum