【发布时间】:2016-12-21 18:38:30
【问题描述】:
单例类公开此方法供客户端获取实例:
template< typename ... Args >
static T & GetInstance( Args && ... args )
{
if ( ! m_instance )
{
m_instance = new T( std::forward< Args >( args ) ... );
}
return * m_instance;
}
但是对于没有默认构造函数的类,总是传递参数很烦人。最好是在实例创建完成后允许用户调用:
auto & instance = GetInstance( );
起初,我认为要使其工作,只需要专门化模板化方法,例如:
// Wrong Version
template< >
static T & GetInstance< >( )
{
if ( ! instance )
{
throw std::runtime_error(
"Tried to get instance of non initialized singleton with no"
" default constructor." );
}
return * instance;
}
但对于具有默认构造函数的类,将使用这种特化代替更通用的特化。我希望只有在T 没有默认构造函数时才使用这种特化。
所以我试着改变一下:
// Right Version
template< >
static auto GetInstance< >( ) ->
typename std::enable_if<
! std::is_default_constructible< T >::value , T & >::type
{
if ( ! instance )
{
throw std::runtime_error(
"Tried to get instance of non initialized singleton with no"
" default constructor." );
}
return * instance;
}
所以这行得通,但我对整个事情感到困惑。首先,我的做法是正确的处理方法吗?我不应该使用enable_if<> 作为参数或模板参数而不是返回类型吗?
编译器在这里是如何工作的?当它只是简单的模板专业化(在错误版本中)时,我猜编译器意识到更专业的版本更适合在没有参数的情况下调用GetInstance()(T 是一个类默认构造函数)。
对于带有enable_if<> 的版本,编译器开始认为使用更专业的版本会更好,但随后代码格式不正确。所以它会退回到普通版本?这也叫 SFINAE 吗?
【问题讨论】:
标签: c++ templates template-specialization sfinae