C++ Instantiation of a struct which have a non-type template

94 Views Asked by At

Usually, we can create one or more instances of a struct the following way:

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;

Unfortunately, it does't seems to be the case when the struct have a template (VSCode give a syntax error):

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;

I can't think of a reason why this would not be allowed. Is there a specific answer on why this is not allowed or is it just because this syntax wasn't defined in the standard?

Edit:

Since it could be viewed as an opinion based question, I would like to know if there is a similar syntax that would work.

1

There are 1 best solutions below

0
On BEST ANSWER

Unlike the case for general structures, The rules says that,

"a template class without a name should not exist"

And if you think about it it make sense. After the end of the definition for an anonymous structure there should be nothing other than name of objects. So there is no room for template parameters.

Also even if it was possible to put the template parameters after an anonymous template, then declaration of 2 objects

<1>Register1, <2>Register2;

together, one after another, would have been another problem!

Using namespace could be an alternative solution that you find useful.

In case you really need the anonymity, another solution might look like this:

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;

Which is not like what you had in mind.

Also If you are going to use the template structure for only a few times, it might worth just writing the equivalent anonymous structures for those few times:


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;

.
.
.