tags:

views:

431

answers:

2

Hello

I want to align my member variables based on a class template type but I'm not sure if it is actually possible.

The following is a (very) simple example of what I'd like to do

template<int Align>
class MyClass
{
private:
  struct MyStruct
  {
    // Some stuff
  } __declspec(align(Align));

  __declspec(align(Align)) int myAlignedVariable;
};

So what I'd like is for Align to be a per-instance variable, and only through that is the align value of the class contents decided.

Unfortunately I always get the following error

error C2975: 'test::MyClass' : invalid template argument for 'Align', expected compile-time constant expression

So, is this actually possible or can the alignment only be possible using a fixed compile time constant? If not, can anyone think of a way around this?

Thanks :)

+3  A: 

Custom alignment isn't in the standard, so how the compilers deal with it is up to them - looks like VC++ doesn't like combining templates with __declspec.

I suggest a work-around using specialisation, something like this:

template<int A> struct aligned;
template<> struct aligned<1> { } __declspec(align(1));
template<> struct aligned<2> { } __declspec(align(2));
template<> struct aligned<4> { } __declspec(align(4));
template<> struct aligned<8> { } __declspec(align(8));
template<> struct aligned<16> { } __declspec(align(16));
template<> struct aligned<32> { } __declspec(align(32));

and then derive from that in your code:

template<int Align>
class MyClass
{
private:
  struct MyStruct : aligned<Align> {
    // stuff
  };
};

This unfortunately breaks the POD-ness of MyStruct. It also doesn't work with built-in/existing types, so you'll have to use a wrapper for those.

aligned_t<int, 4> myAlignedVariable;
pmjordan
why not make he "aligned" the first member of the MyStruct? then it's still pod.
Johannes Schaub - litb
+3  A: 

Boost has solved this problem already. They use the technique in boost::optional (link to header), which has to hold enough space for an aligned, arbitrary type but can't (won't) actually instantiate that object on construction.

Their solution was to allocate a simple pool of bytes (char array) and use in-place new to construct objects at the desired location. The address given to in-place new can be of any arbitrary alignment.

That being said, you're saying that you're giving a very simple example in your question. What is the actual problem that you're trying to solve by implementing a class where every member has a user-specified alignment that doesn't vary per member but can vary per class instance?

Shmoopty
That's what I'm doing at the moment with our allocation model, and it works well. But it was requested that we might ensure the alignment was enforced if structures were outside the allocator.To be honest, I'm pretty happy that what we have already does the job, and this has confirmed that.
Lee Winder