如果给定模板参数,则使用sfinae启用构造函数提供类型定义

enabling a constructor with sfinae if given template argument provides a type definition

本文关键字:构造函数 启用 sfinae 定义 类型 参数 如果      更新时间:2023-10-16

根据给定类型作为模板形参是否定义了类型,我希望在模板类中启用两个构造函数中的一个且仅一个。

这里,我想在构造函数中添加来自给定模板的定义类型作为附加参数,如果存在该参数,则转发该参数。但见:

class A
{  // this class did not provide ConstructorParms type definition
    public:
        A( int i) {}
};
class B
{  // this class provide the type ConstructorParms
    public:
        using ConstructorParms= double;
        B( double d, int i) {}
};

template <typename T>
class Check: public T
{
    public:
        // ??? enable_if T has typename T::ConstructorParms
        Check( typename T::ConstructorParms parms, int i): T( parms, i) {}
        // ??? enable_if T has NOT typename T::ConstructorParms
        Check( int i): T(i){}
};
int main()
{
    Check<A> ca(9);             
    Check<B> cb(1.23, 10);
    return 0;
}

我遇到了麻烦,因为构造函数"method"本身没有模板parm。任何想法?

注意(给出答案的原因):代码片段确实简化了。用using转发给父构造函数是不可能的,因为现实世界中的类Check需要一些参数作为它们自己的参数。这使得转发到父构造函数是不可能的。

你可以使用SFINAE来解决这个问题,但自c++ 11以来,有一个更简单的解决方案:继承的构造函数。

template <typename T>
class Check: public T
{
    public:
        using T::T;
};

如果构造函数不仅仅做转发;使用以下通用解决方案:

#include <type_traits>
template< typename T >
struct HasCtorParamTypedef
{
    template< typename U,
              typename = typename U::ConstructorParms >
    static int f( U );
    static void f( ... );
    static const bool value = std::is_same<decltype(f(std::declval<T>())), int>::value;
};
template <typename T>
struct Check: public T
{
        // Is only enabled if T does have the typedef
        template <typename U = T,
                  typename = typename std::enable_if<HasCtorParamTypedef<U>::value>::type >
        Check( typename U::ConstructorParms parms, int i): T( parms, i) {}
        // Is only enabled if T does **not** have the typedef
        template <typename U = T,
                  typename = typename std::enable_if<!HasCtorParamTypedef<U>::value>::type >
        Check( int i ): T(i){}
};