繁体   English   中英

可变参数模板专业化,std :: enable_if,SFINAE

[英]Variadic template specialization, std::enable_if, SFINAE

单例类为客户端公开此方法以获取实例:

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是具有默认construtor的类)。

对于带有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为空并且是首选时,第二个更专业。


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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM