在base-clause中使用类中定义的typedef / type别名

时间:2015-12-12 17:42:43

标签: c++ inheritance

我常常遇到类定义中不可避免的重复代码的问题,即我在base-clause中键入base-specifiers,然后我应该为每个非默认构造的基类输入/复制相同的代码至少一次:在构造函数中(在成员初始化列表中或在其主体中)。两次输入其中一些是令人讨厌的事情。我看到了问题的解决方案:是允许用户在typedef的base-clause中使用,键入在当前类范围中定义的别名和别名模板。即在定义之前,它允许在当前类范围(数据成员,成员函数)中定义的其他符号。

是否存在 C ++ 所强加的 C ++ 性质的限制,以允许转发使用类范围中定义的typedef / type别名/别名模板?

例如:

template< bool >
struct enable_default_constructor;

template<>
struct enable_default_constructor< true >
{
    enable_default_constructor() = default; 
    enable_default_constructor(void * ) { ; }
};

template<>
struct enable_default_constructor< false >
{
    enable_default_constructor() = delete; 
    enable_default_constructor(void * ) { ; }
};

template< typename ...Ts >
struct X
    : enable_default_constructor< (std::is_default_constructible< Ts >::value && ...) >
{

    // next line containing duplication of code
    using enabler = enable_default_constructor< (std::is_default_constructible< Ts >::value && ...) >;

    X() = default;

    template< typename ...Us >
    X(Us &&... v)
        : enabler({})
        , m(std::forward< Us >(v)...) // using symbol `m` before definition
    { ; }

private :

    std::tuple< Ts... > m;

};

struct S {};
struct N { N() = delete; };

static_assert(std::is_default_constructible< X< int, double, S > >::value);
static_assert(!std::is_default_constructible< X< int, double, N > >::value);

我想直接在base-clause中使用enabler符号。

2 个答案:

答案 0 :(得分:1)

如果我认为你想要避免编写基类的名称(例如因为它是一个冗长,复杂的模板),那么就会有一种稍微复杂的方法。

将此应用于您的上述要求:

template< bool >
struct enable_default_constructor;

template<>
struct enable_default_constructor< true >
{
    enable_default_constructor() = default;
    enable_default_constructor(void * ) { ; }
};

template<>
struct enable_default_constructor< false >
{
    enable_default_constructor() = delete;
    enable_default_constructor(void * ) { ; }
};

namespace declare_X
{

    template<typename ...Ts> using
    base = ::enable_default_constructor< (std::is_default_constructible< Ts >::value && ...) >;

    template< typename ...Ts >
    struct X
    : base<Ts...>
    {

        X() = default;

        X(Ts &&... v)
        : base<Ts...>({})
        , m(std::forward< Ts >(v)...)
        { ; }

        private :

        std::tuple< Ts... > m;

    };

}
template<typename...Ts> using X = declare_X::X<Ts...>;


struct S {};
struct N { N() = delete; };

static_assert(std::is_default_constructible< X< int, double, S > >::value);
static_assert(!std::is_default_constructible< X< int, double, N > >::value);
  

但我不想重复模板参数......

然后我担心我们不得不求助于宏:

#if defined(BASE_CLASS)
#undef BASE_CLASS
#endif

#define BASE_CLASS enable_default_constructor< (std::is_default_constructible< Ts >::value && ...) >


template< typename ...Ts >
struct X
: BASE_CLASS
{

    X() = default;

    X(Ts &&... v)
    : BASE_CLASS({})
    , m(std::forward< Ts >(v)...)
    { ; }

    private :

    std::tuple< Ts... > m;

};

#undef BASE_CLASS

答案 1 :(得分:0)

通过对类模板定义进行少量修改,您可以将繁重的类型粘贴到模板参数列表中:

namespace internal
{
    template <typename, typename> struct XImpl;

    template <typename ...Args, typename Enabler>
    struct XImpl<std::tuple<Args...>, Enabler> : Enabler
    {
        using XImpl() = default;
        // ...
    };
}

template <typename ...Args>
using X = internal::XImpl<std::tuple<Args...>,
                          HorrendousEnablerTemplate<Args...>>;