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 ?