簡體   English   中英

在基本子句中使用類中定義的typedef / type別名

[英]Using in-class defined typedefs/type aliases in base-clause

通常,我會遇到不可避免的類定義代碼重復的問題,即我在基本子句中鍵入基本說明符,然后對於每個非默認構造的基類,我應該至少再鍵入/復制一次相同的代碼:在構造函數中(在成員初始值設定項列表或其主體中)。 兩次鍵入其中的一些內容很煩人。 我看到了問題的解決方案:是允許用戶在當前類作用域中定義的typedef,類型別名和別名模板的基礎子句中使用。 即在其定義之前,因為它允許在當前類范圍內定義其他符號(數據成員,成員函數)。

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);

我想直接在基本條款中使用enabler符號。

如果我認為您想避免寫基類的名稱(例如,因為它是一個長而復雜的模板),那是一種正確的做法。

將其應用於您的上述要求:

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

只需對類模板定義進行少量修改,就可以將繁瑣的類型粘貼到模板參數列表中:

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...>>;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM