繁体   English   中英

如何专门化模板类的成员结构

[英]How to specialize a templated class's member struct

假设我有以下模板类:

template<typename T>
class Foo {
    struct store_t {
        uint8_t data[];
    } store;
    /// other stuff using T
}

有没有办法构建一个内部结构的专用版本,等同于这样的东西:

class Foo {
    struct store_t {
        uint16_t f1;
        uint16_t f2;
    } store;
    /// other stuff using T
}

我宁愿保留大部分“使用T的其他东西”非专业化。 我会专门研究一些访问者。 我觉得我想要写一些类似的东西

template<>
struct store_t {
    uint16_t f1;
    uint16_t f2;
} Foo<someT>::store;

但那当然不行。

与生活中的大多数事情一样,“如何通过模板解决这个问题”的答案是“使用更多模板”。

解决方案1 ​​ - 将store_t写为模板

值得庆幸的是,我们不必做任何疯狂的事情。 让我们写store_t之外Foo作为模板:

template<bool use_uint8>
struct Foo_store_t {
    uint8_t data[]; 
};
template<>
struct Foo_store_t<false> {
    uint16_t f1;
    uint16_t f2;
};

现在,在编写Foo ,我们可以通过测试某些条件来选择我们想要使用的那个:

template<class T>
class Foo {
    constexpr static bool use_uint8 = /* stuff */; 
    using store_t = Foo_store_t<use_uint8>; 
    store_t store;
};

解决方案2 - 编写store_t两个版本,使用std::conditional

这个也非常简单。 std::conditional允许您使用布尔值在两个不同(任意)类型之间进行选择。

struct store_A {
    uint8_t data[];
};
struct store_B {
    uint16_t f1;
    uint16_t f2;
};
class Foo {
    constexpr static bool useVersionA = /* stuff */; 
    using store_t = std::conditional_t<useVersionA, store_A, store_B>; 
};

这里我使用的是std::conditional_t ,它出现在C ++ 14中,但是如果你只能使用C ++ 11,那就做:

class Foo {
    constexpr static bool useVersionA = /* stuff */; 
    using store_t = typename std::conditional<useVersionA, store_A, store_B>::type; 
};

为了好玩,我展示了一种基于某种自我继承的可能解决方案。

假设你想为bool类型使用specialize Foo

您可以编写主Foo添加一个带有默认值的模板非类型参数(比如一个默认值为truebool

template <typename T, bool = true>
struct Foo
 {
    struct store_t
     { std::uint8_t data[10]; }   store;

    /// other stuff using T
    T value;
 };

我添加了T value作为“使用T的其他东西”的例子。

现在,你可以专注Foo<bool>继承Foo<bool, false>

template <>
struct Foo<bool> : public Foo<bool, false>
 {
    struct store_t
     { std::uint16_t f1, f2; }   store;
 };

这样你就可以专门化store_t / store (以及其他成员,如果你愿意的话)继承自Foo<bool, false> “使用T的其他东西”( bool value ,例如)。

以下是完整的编译示例

#include <cstdint>
#include <type_traits>

template <typename T, bool = true>
struct Foo
 {
    struct store_t
     { std::uint8_t data[10]; }   store;

    T value;
 };

template <>
struct Foo<bool> : public Foo<bool, false>
 {
    struct store_t
     { std::uint16_t f1, f2; }   store;

    // inherits a bool value from Foo<bool, false>
 };

int main()
 {
   Foo<int>   fi;
   Foo<bool>  fb;

   static_assert( std::is_same<decltype(fi.value),
                               int>::value, "!");
   static_assert( std::is_same<decltype(fi.store.data),
                               std::uint8_t[10]>::value, "!");
   static_assert( std::is_same<decltype(fb.value),
                               bool>::value, "!");
   static_assert( std::is_same<decltype(fb.store.f2),
                               std::uint16_t>::value, "!");
 }

暂无
暂无

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

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