1

Please have a look at the following example code

template < typename TYPE >
struct foo
{
    static TYPE bar;
};

template < typename TYPE >
TYPE foo < TYPE >::bar;

template < typename RET, typename... ARGS >
struct changer
{
    typedef std::function < RET ( ARGS... ) > type;

    static void set ( type v ) { foo < type >::bar = v; }

    static type get () { return foo < type >::bar; }
};

void custom_func ( int i )
{
    std::cout << "called with " << i << std::endl;
}

struct initializer
{
    typedef changer < void, int > changer_t;

    initializer ()
    {
        changer_t::set ( std::bind ( & custom_func, std::placeholders::_1 ) );
        call ( 1 );
    }

    void call ( int v )
    {
        auto myfunc = changer_t::get ();

        if ( myfunc ) myfunc ( v );
        else std::cout << "myfunc is empty" << std::endl;
    }
};

initializer x;

int main()
{
    x.call ( 2 );

    return 0;
}

The output of that program is

called with 1
myfunc is empty

And when I change foo and changer to not-template code

struct foo
{
    static std::function < void ( int ) > bar;
};

std::function < void ( int ) > foo::bar;

struct changer
{
    typedef std::function < void ( int ) > type;

    static void set ( type v ) { foo::bar = v; }

    static type get () { return foo::bar; }
};

The output is what I would've also expected for the first version:

called with 1
called with 2

What is happening here ? And how can I make it work with the templated version ?

Tested with MSVC2013 and g++ templated | not-templated

Update: I just accidently built in release mode in VS, in which the templated version outputs

called with 1
called with 2

... Am I tickling UB ?

andyb
  • 95
  • 7
  • Is this program only valid with c++11? – user1436187 Nov 15 '15 at 06:50
  • @user1436187 Not sure why c++11 is open for debate, but I [changed](http://coliru.stacked-crooked.com/a/c7f1b1569448d79f) it to 03, same results for templated version. – andyb Nov 15 '15 at 07:00

1 Answers1

0

Static members of templates have unordered initialisation. That means bar may (but also may not) be initialised too late for your purposes - after x is initialised.

(That isn't true for non-templates, which is why that case works for you.)

See also Initialization order of static data inside class template.

Community
  • 1
  • 1
Alan Stokes
  • 18,815
  • 3
  • 45
  • 64