Problems with void Template Type Parameters and Zero-Length Arrays

M

Matt Taylor

I am trying to use templates to create an optimal structure for a fixed-size
buffer that holds a homogenous array of elements. For brevity, this problem
is somewhat simplified from my implementation:

template<typename T1, size_t len>
struct buffer_t
{
// Array of elements
T1 ary[len / sizeof(T1)];

// Align upward to a multiple of sizeof(T1)
char pad[len - ((len / sizeof(T1)) * sizeof(T1))];
};

The problem is that, when len is a multiple of sizeof(T1), the pad variable
has length 0. For some reason the compiler finds this to be absurd. I need
to find some way to make this compile in that case. Is there any simple
resolution to this?

I am also wondering about the following:
template<typename T>
struct A
{
int a;
T b;
};

struct INGET
{
};

Why is A<INGET> legal but not A<void>? Semantically they would be the same,
right?

-Matt
 
R

Rob Williscroft

Matt Taylor wrote in in comp.lang.c++:
The problem is that, when len is a multiple of sizeof(T1), the pad
variable has length 0. For some reason the compiler finds this to be
absurd. I need to find some way to make this compile in that case. Is
there any simple resolution to this?

#include <iostream>
#include <cstddef>

using std::size_t;

template <typename T1, size_t len>
struct padding
{
static size_t const value = len - ((len / sizeof(T1)) * sizeof(T1));
};

template < typename T, size_t Count, size_t Pad >
struct base_buffer_t
{
T ary[ Count ];
char pad[ Pad ];
};

template < typename T, size_t Count >
struct base_buffer_t< T, Count, 0U >
{
T ary[ Count ];
typedef void pad; /* for using */
};


template <typename T1, size_t len>
struct buffer_t :
private base_buffer_t<
T1, len / sizeof(T1), len - ((len / sizeof(T1)) * sizeof(T1)){
private:

typedef base_buffer_t<
T1, len / sizeof(T1), len - ((len / sizeof(T1)) * sizeof(T1))base_t
;

public:

using base_t::ary;
using base_t::pad;
};


int main()
{
buffer_t< int, sizeof( int ) * 2 > int2;
int2.ary[1] = 2;

buffer_t< int, (sizeof( int ) * 1) + 1 > int1p1;

std::cout << sizeof( int2 ) << '\n';
std::cout << sizeof( int1p1 ) << '\n';
}

I am also wondering about the following:
template<typename T>
struct A
{
int a;

This next line can't compile if the substitution T = void is done.
T b;
};

struct INGET
{
};

Why is A<INGET> legal but not A<void>? Semantically they would be the
same, right?

Its illegal because:

void b;

is illegal, i.e. you cannot declare objects of type void.

HTH.

Rob.
 
M

Matt Taylor

Rob Williscroft said:
Matt Taylor wrote in in comp.lang.c++: [...]
Its illegal because:

void b;

is illegal, i.e. you cannot declare objects of type void.

Yeah, I know. I was mostly wondering the logic behind why one can create and
instantiate a structure with length 0 but not an object of type void since
they seem to me to be the same idea. This is very strange because you can
create a typedef which is just an alias for void, but you can't use void
itself.

Anyhow, thank you for your reply -- it has helped greatly.

-Matt
 
R

Ron Natalie

Matt Taylor said:
Yeah, I know. I was mostly wondering the logic behind why one can create and
instantiate a structure with length 0 but not an object of type void since
they seem to me to be the same idea.

You can't create a structure of size 0. You can create a structure with no data
members in it, but it will still have size greater than zero.
 
O

Old Wolf

Matt Taylor said:
I am trying to use templates to create an optimal structure for a fixed-size
buffer that holds a homogenous array of elements. For brevity, this problem
is somewhat simplified from my implementation:

template<typename T1, size_t len>
struct buffer_t
{
// Array of elements
T1 ary[len / sizeof(T1)];

// Align upward to a multiple of sizeof(T1)
char pad[len - ((len / sizeof(T1)) * sizeof(T1))];
};

The problem is that, when len is a multiple of sizeof(T1), the
pad variable has length 0.

Do you need to be able to reference 'pad' ? If not then you
could try:

template<typename T1, size_t len>
union buffer_t
{
T1 ary[len / sizeof(T1)];
char pad[len];
};

(If you need other data members in buffer_t then you would
have to make it a struct, and have a member union).
 
M

Matt Taylor

Old Wolf said:
The problem is that, when len is a multiple of sizeof(T1), the
pad variable has length 0.

Do you need to be able to reference 'pad' ? If not then you
could try:

template<typename T1, size_t len>
union buffer_t
{
T1 ary[len / sizeof(T1)];
char pad[len];
};

Ah, I had not thought of this. This is a very simple and intuitive way to
make it work.

My thanks and appreciation to both posters.

-Matt
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top