variadic模板专业化,std :: enable_if,sfinae

Variadic template specialization, std::enable_if, SFINAE

本文关键字:enable if sfinae std 专业化 variadic      更新时间:2023-10-16

singleton类公开了此方法,以获取实例:

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?

方便的经验法则:不要专业,超负荷。

template <class... Args>
static T& GetInstance(Args&&... );
template <class U=T, std::enable_if_t<!std::is_default_constructible<U>::value, int> = 0>
static T& GetInstance();

如果T默认可构造,则只有一个可行的过载。如果不是这样,那么当Args是空并且首选时,第二个更专业。


注意。这个设计似乎令人怀疑。