簡體   English   中英

如何為模板的內部類型專門化一個類?

[英]How to specialize a class for an inner type of a template?

我有一個充當類型特征的類,返回某個條件是否為真。 它旨在將類標記為支持特定功能。

template <typename T> struct Check : std::false_type { };

我有一個包含內部類的模板類:

template <unsigned N>
struct Kitty
{
  struct Purr;
};

我想將內部類Purr標記為支持表示為Check的功能。 換句話說,我想使Check<Kitty<123>::Purr>::valuetrue 我嘗試執行以下操作,但出現錯誤:

template <unsigned X>
struct Check<typename Kitty<X>::Purr> : std::true_type { };

錯誤:無法在部分專業化中推導模板參數:

是否有可能做到這一點,還是您不能專門研究內部模板類成員的C ++局限性?

這個答案有一種有趣的方法,可以使用SFINAE查找類型是否存在。

適應檢查類型T :: Purr是否存在,它使您可以編寫類型特征而不會出現問題的專業化。

#include <type_traits>

template <unsigned T>
struct Kitty
{
    struct Purr{};
};

// A specialization without Purr, to test
template <>
struct Kitty<5>{ };

// has_purr is taken and adapted from https://stackoverflow.com/a/10722840/7359094
template<typename T>
struct has_purr
{   
    template <typename A> 
    static std::true_type has_dtor(decltype(std::declval<typename A::Purr>().~Purr())*);

    template<typename A>
    static std::false_type has_dtor(...);

    typedef decltype(has_dtor<T>(0)) type;

    static constexpr bool value = type::value;
};

// Check if a type is an instance of Kitty<T>
template<typename T>
struct is_kitty : std::false_type {};
template<unsigned T>
struct is_kitty<Kitty<T>> : std::true_type {};

template <typename T> 
struct Check : std::bool_constant< is_kitty<T>::value && has_purr<T>::value> {};

static_assert( Check<int>::value == false, "int doesn't have purr" );
static_assert( Check<Kitty<0>>::value == true, "Kitty<0> has purr" );
static_assert( Check<Kitty<5>>::value == false, "Kitty<5> doesn't has purr" );

正如我的評論中概述的那樣,可以通過使用基類(我稱為KittyBase來將其推論為上下文。 實際上,對於模板而言,通常使用基類,以避免為每個新實例重復不必要的代碼。 我們可以使用相同的技術來獲得Purr而無需推導N

但是,僅將Purr放在基類中將刪除對N訪問。 幸運的是,即使將Purr本身作為模板,這仍然可以是一個非推論的上下文: 實時示例

#include <type_traits>

template <typename T> struct Check : std::false_type { };

struct KittyBase 
{    
    template<unsigned N> // Template if Purr needs N.
    struct Purr;

protected:
    ~KittyBase() = default; // Protects against invalid polymorphism.
};

template <unsigned N>
struct Kitty : private KittyBase
{
    using Purr = KittyBase::Purr<N>; // Convenience if Purr needs N.
    Purr* meow;
};

template <unsigned X>
struct Check<typename KittyBase::Purr<X>> : std::true_type { };

static_assert(not Check<int>{});
static_assert(Check<Kitty<123>::Purr>{});
static_assert(Check<Kitty<0>::Purr>{});

int main() {}

如果願意,您甚至可以將KittyBase::Purr私有,並使用template<typename T> friend struct Check; 授予對特征的訪問權限。 不幸的是,我不知道您是否可以將其限制為僅該特性的某些專業化。

暫無
暫無

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

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