首页 > 解决方案 > 如何专门化模板类的成员结构

问题描述

假设我有以下模板类:

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;

但这当然行不通。

标签: c++templatestemplate-specialization

解决方案


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

store_t解决方案 1 -作为模板编写

谢天谢地,我们不必做任何疯狂的事情。让我们在模板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; 
};

推荐阅读