请查看以下示例代码
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;
}
该程序的输出是
called with 1
myfunc is empty
当我将foo
和changer
更改为非模板代码
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; }
};
输出是我对第一个版本所期望的:
called with 1
called with 2
这里发生了什么?如何使其与模板化版本一起使用?
使用MSVC2013和g ++ templated |进行测试not-templated
更新:我只是意外地在VS中构建了发布模式,其中模板化版本输出
called with 1
called with 2
......我在挠痒UB吗?
答案 0 :(得分:0)
模板的静态成员具有无序初始化。这意味着bar
可能(但也可能不会)在初始化x
之后为您的目的初始化太晚。
(对于非模板,情况并非如此,这就是为什么这种情况适合你的原因。)
另见Initialization order of static data inside class template。