一个单例类向客户端公开此方法以获取该实例:
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吗?
class U=T
,然后再使用U
?这与重载解决有关吗? - Tarcis_default_constructible<T>::value
,其中T
不是模板参数,则会立即评估并出现硬错误。 - Barry