[英]How to specialize a templated class's member struct
Say I have the following templated class: 假设我有以下模板类:
template<typename T>
class Foo {
struct store_t {
uint8_t data[];
} store;
/// other stuff using T
}
Is there a way to construct a specialized version of the internal struct that would equate to something like this: 有没有办法构建一个内部结构的专用版本,等同于这样的东西:
class Foo {
struct store_t {
uint16_t f1;
uint16_t f2;
} store;
/// other stuff using T
}
I would prefer to keep most of the "other stuff using T" unspecialized. 我宁愿保留大部分“使用T的其他东西”非专业化。 I would specialize some accessors though.
我会专门研究一些访问者。 I feel I would want to write something like
我觉得我想要写一些类似的东西
template<>
struct store_t {
uint16_t f1;
uint16_t f2;
} Foo<someT>::store;
but that of course doesn't work. 但那当然不行。
As with most things in life, the answer to "how do I solve this problem I'm having with templates" is "use more templates." 与生活中的大多数事情一样,“如何通过模板解决这个问题”的答案是“使用更多模板”。
store_t
as a template store_t
写为模板 Thankfully, we don't have to do anything crazy. 值得庆幸的是,我们不必做任何疯狂的事情。 Let's write
store_t
outside of Foo
as a template: 让我们写
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;
};
Now, when writing Foo
, we can just pick which one we wanna use by testing some condition: 现在,在编写
Foo
,我们可以通过测试某些条件来选择我们想要使用的那个:
template<class T>
class Foo {
constexpr static bool use_uint8 = /* stuff */;
using store_t = Foo_store_t<use_uint8>;
store_t store;
};
store_t
, use std::conditional
store_t
两个版本,使用std::conditional
This one is also pretty straight-forward. 这个也非常简单。
std::conditional
lets you pick between two different (arbitrary) types using a boolean. 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>;
};
Here I'm using std::conditional_t
, which appears in C++14, but if you're restricted to using C++11 just do: 这里我使用的是
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;
};
Just for fun, I show another possible solution based over a sort of self-inheritance. 为了好玩,我展示了一种基于某种自我继承的可能解决方案。
Suppose you want specialize Foo
for the type bool
. 假设你想为
bool
类型使用specialize Foo
。
You can write the main Foo
adding a template non-type parameter with a default value (say a bool
with a default value of true
) 您可以编写主
Foo
添加一个带有默认值的模板非类型参数(比如一个默认值为true
的bool
)
template <typename T, bool = true>
struct Foo
{
struct store_t
{ std::uint8_t data[10]; } store;
/// other stuff using T
T value;
};
I've added T value
as example of "other stuff using T". 我添加了
T value
作为“使用T的其他东西”的例子。
Now you can specialize Foo<bool>
inheriting from Foo<bool, false>
现在,你可以专注
Foo<bool>
继承Foo<bool, false>
template <>
struct Foo<bool> : public Foo<bool, false>
{
struct store_t
{ std::uint16_t f1, f2; } store;
};
This way you can specialize store_t
/ store
(and other members, if you want) inheriting from Foo<bool, false>
the "other stuff using T" (a bool value
, by example). 这样你就可以专门化
store_t
/ store
(以及其他成员,如果你愿意的话)继承自Foo<bool, false>
“使用T的其他东西”( bool value
,例如)。
The following is a full compiling example 以下是完整的编译示例
#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.