具有非类型模板的结构的 C++ 实例化
C++ Instantiation of a struct which have a non-type template
通常,我们可以通过以下方式创建一个或多个结构实例:
struct
{
const uint8_t Address;
struct
{
uint8_t GPIO1 : N;
uint8_t GPIO2 : N;
uint8_t GPIO3 : N;
uint8_t GPIO4 : N;
uint8_t GPIO5 : N;
uint8_t GPIO6 : N;
uint8_t GPIO7 : N;
uint8_t GPIO8 : N;
} Value;
} Register1, Register2;
不幸的是,当结构有模板时似乎不是这种情况(VSCode 给出语法错误):
template<uint8_t N = 1> struct
{
const uint8_t Address;
struct
{
uint8_t GPIO1 : N;
uint8_t GPIO2 : N;
uint8_t GPIO3 : N;
uint8_t GPIO4 : N;
uint8_t GPIO5 : N;
uint8_t GPIO6 : N;
uint8_t GPIO7 : N;
uint8_t GPIO8 : N;
} Value;
} <1>Register1, <2>Register2;
我想不出不允许这样做的原因。是否有关于为什么不允许这样做的具体答案,或者仅仅是因为标准中未定义此语法?
编辑:
因为它可以被视为一个基于意见的问题,我想知道是否有类似的语法可以工作。
与一般结构的情况不同,规则规定,
“不应该存在没有名称的模板class”
如果你仔细想想,这是有道理的。在匿名结构的定义结束之后,除了对象名称之外应该没有其他内容。所以没有模板参数的余地。
同样,即使可以将模板参数放在匿名模板之后,然后声明 2 个对象
<1>Register1, <2>Register2;
一起,一个接一个,又是一个问题!
使用命名空间可能是您认为有用的替代解决方案。
如果您真的需要匿名,另一种解决方案可能如下所示:
struct{
template<uint8_t N = 1>
struct Reg
{
const uint8_t Address{};
struct
{
uint8_t GPIO1 : N;
uint8_t GPIO2 : N;
uint8_t GPIO3 : N;
uint8_t GPIO4 : N;
uint8_t GPIO5 : N;
uint8_t GPIO6 : N;
uint8_t GPIO7 : N;
uint8_t GPIO8 : N;
} Value;
};
Reg<1> Register1;
Reg<2> Register2;
}Regs;
uint8_t v1 = Regs.Register1.Address;
uint8_t v2 = Regs.Register2.Address;
这和你想的不一样。
此外,如果您只打算使用模板结构几次,那么只为那几次编写等效的匿名结构可能值得:
struct
{
const uint8_t Address{};
struct
{
uint8_t GPIO1 : 1;
uint8_t GPIO2 : 1;
uint8_t GPIO3 : 1;
uint8_t GPIO4 : 1;
uint8_t GPIO5 : 1;
uint8_t GPIO6 : 1;
uint8_t GPIO7 : 1;
uint8_t GPIO8 : 1;
} Value;
}Register1;
struct
{
const uint8_t Address{};
struct
{
uint8_t GPIO1 : 2;
uint8_t GPIO2 : 2;
uint8_t GPIO3 : 2;
uint8_t GPIO4 : 2;
uint8_t GPIO5 : 2;
uint8_t GPIO6 : 2;
uint8_t GPIO7 : 2;
uint8_t GPIO8 : 2;
} Value;
}Register2;
.
.
.
通常,我们可以通过以下方式创建一个或多个结构实例:
struct
{
const uint8_t Address;
struct
{
uint8_t GPIO1 : N;
uint8_t GPIO2 : N;
uint8_t GPIO3 : N;
uint8_t GPIO4 : N;
uint8_t GPIO5 : N;
uint8_t GPIO6 : N;
uint8_t GPIO7 : N;
uint8_t GPIO8 : N;
} Value;
} Register1, Register2;
不幸的是,当结构有模板时似乎不是这种情况(VSCode 给出语法错误):
template<uint8_t N = 1> struct
{
const uint8_t Address;
struct
{
uint8_t GPIO1 : N;
uint8_t GPIO2 : N;
uint8_t GPIO3 : N;
uint8_t GPIO4 : N;
uint8_t GPIO5 : N;
uint8_t GPIO6 : N;
uint8_t GPIO7 : N;
uint8_t GPIO8 : N;
} Value;
} <1>Register1, <2>Register2;
我想不出不允许这样做的原因。是否有关于为什么不允许这样做的具体答案,或者仅仅是因为标准中未定义此语法?
编辑:
因为它可以被视为一个基于意见的问题,我想知道是否有类似的语法可以工作。
与一般结构的情况不同,规则规定,
“不应该存在没有名称的模板class”
如果你仔细想想,这是有道理的。在匿名结构的定义结束之后,除了对象名称之外应该没有其他内容。所以没有模板参数的余地。
同样,即使可以将模板参数放在匿名模板之后,然后声明 2 个对象
<1>Register1, <2>Register2;
一起,一个接一个,又是一个问题!
使用命名空间可能是您认为有用的替代解决方案。
如果您真的需要匿名,另一种解决方案可能如下所示:
struct{
template<uint8_t N = 1>
struct Reg
{
const uint8_t Address{};
struct
{
uint8_t GPIO1 : N;
uint8_t GPIO2 : N;
uint8_t GPIO3 : N;
uint8_t GPIO4 : N;
uint8_t GPIO5 : N;
uint8_t GPIO6 : N;
uint8_t GPIO7 : N;
uint8_t GPIO8 : N;
} Value;
};
Reg<1> Register1;
Reg<2> Register2;
}Regs;
uint8_t v1 = Regs.Register1.Address;
uint8_t v2 = Regs.Register2.Address;
这和你想的不一样。
此外,如果您只打算使用模板结构几次,那么只为那几次编写等效的匿名结构可能值得:
struct
{
const uint8_t Address{};
struct
{
uint8_t GPIO1 : 1;
uint8_t GPIO2 : 1;
uint8_t GPIO3 : 1;
uint8_t GPIO4 : 1;
uint8_t GPIO5 : 1;
uint8_t GPIO6 : 1;
uint8_t GPIO7 : 1;
uint8_t GPIO8 : 1;
} Value;
}Register1;
struct
{
const uint8_t Address{};
struct
{
uint8_t GPIO1 : 2;
uint8_t GPIO2 : 2;
uint8_t GPIO3 : 2;
uint8_t GPIO4 : 2;
uint8_t GPIO5 : 2;
uint8_t GPIO6 : 2;
uint8_t GPIO7 : 2;
uint8_t GPIO8 : 2;
} Value;
}Register2;
.
.
.