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 :)
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;
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?
Related
Is it possible to make an array of a struct with template type fields?
template<typename T>
struct MyStruct {
T *pField;
};
MyStruct< ?? > mystruct_arr[] = {
{ pFieldOfType1 },
{ pFieldOfType2 },
};
The above obviously doesn't work, but is it possible with other techniques?
I am trying to loop through the array mystruct_arr and call this function on every struct row:
template<typename T>
void SetupField(T &pSourceField, ...)
{
Base *field = ...->findBaseFieldFromDatabase(...);
...
pSourceField = static_cast<T>(field);
...
}
The reason is to try to refactor a very repetitive piece of code where I have to static_cast a long list of different types according to a few different arguments, without making it overly complicated.
A template is not a class, or a struct. It can be thought of as a blueprint, or a recipe, for a class or a struct that gets created when the template gets instantiated.
A template becomes an actual class or a struct only when it is instantiated, by specifying the required template parameters:
MyStruct<int>
Now you have an actual, living, breathing class here. But a MyStruct<int> would be a completely different class than MyStruct<char>. Without specifying the template parameters, MyStruct is not a class, or a struct, or anything that takes up a single byte of RAM. It's just a template for some struct or class.
But with template parameters, such as MySutrct<int>, this becomes an actual class with fields, and perhaps methods. Now that you have a class you can certainly have an array of these, now:
MyStruct<int> mystruct_arr[] = {
};
Or you could have a different array of MyStruct<char>s:
MyStruct<char> mystruct_arr2[] = {
};
But you can't have an array that contains both of these for the same, exact, precise reason that you can't have a single array containing a smorgasbord of different types and classes. You can't have an array that contains both chars, ints, floats, pointers, or various classes. An array always contains values of the same type/class. So pick one particular MyStruct<whatever>, and make an array out of it, that's all you can do.
But you can also declare another structure, now:
struct many_structs {
MyStruct<int> int_struct;
MyStruct<char> char_struct;
// ...
};
This sort of starts to look like an array you would like to have. But it's not an array. It's just an ordinary struct; and instead of using an array index to access a particular template instance, you would refer to the struct member directly.
You could, with some additional work, specialize std::get for your structure, and make this structure look like an array. But now you just realized that you reinvented std::tuple, and can simply to do this:
std::tuple<MyStruct<int>, MyStruct<char>> mystruct_tuple;
Finally, the closest approximation to what you're trying to do is possible only with some additional work, and with a C++ compiler that supports C++17, by declaring an array containing std::anys, or perhaps std::variants. If the array should only contain an a limited enumeration of template instances, std::variant gives the most type-safety, and convenience:
std::variant<MyStruct<int>, MyStruct<char>> mystruct_arr[]={
};
The resulting array contains only these two particular template instances. And with std::any, the screws get loosened further but you'll have to do more work to use and access each value in the array.
You think you want an array of templates.
What you really want is an array of types you can call a particular template function on.
The first is not possible. The second is called type erasure in C++.
template<class T>
using setup_fptr=void(*)(T &, Foo)
using gen_setup_ptr=void(*)(void*, Foo);
template<class T>
setup_ptr<T> get_setup(){ return SetupField<T>; }
template<class T>
gen_setup_ptr get_gen_setup(){
return [](void* p, Foo f){ get_setup<T>( *static_cast<T*>(p), f ); };
}
struct can_setup {
void* ptr=0;
gen_setup_ptr f=0;
can_setup(can_setup const&)=default;
can_setup& operator=(can_setup const&)=default;
can_setup()=default;
explicit operator bool() const{return f;}
template<class T>
can_setup(T* pt):
ptr(pt),
f( get_gen_setup<T>() )
{}
void setup( Foo foo ) const {
f(ptr, foo );
}
};
store an array of can_setup. Loop over them calling .setup(foo).
Foo is a placeholder for whatever other args you are using.
This technique is known as type erasure; we forget (erase) everything about T except that we can setup it.
Yesterday, I stumbled upon an library named Eigen, it provides an array class that has signature like this:-
Array<float,Dynamic,1> b;//<--- dynamic = unknown at compile time
Array<float,3,1> c;//<--- both row(=3) and col(=1) known at compile time
Here is the source code of Array.h and a closely related class PlainObjectBase.h.
As far as I can guess (from digging), if both row and col are known at compile time, it will allocate memory as stack variable, same way as:-
float c[3];
I think it is very cool, because it can avoid unnecessary heap allocation.
It is very suitable in some situation.
Question
What are the C++ technique/semantic to create collection that support both fix & dynamic size within 1 class?
What are the ideas behind it?
I am not asking for a full code or any snippet, but I don't mind it.
Answer can ignore all fact about how Eigen Array is implemented. (Eigen is just an example.)
I want some solid idea to improve my own array encapsulator to be cool like that.
My poor solution
Create fields for both scenario (dynamic & fix), but in each scenario, use only some of them.
Then, spam std::enable_if to control Dynamic vs Const, but I think it is anti-pattern.
They do it with partial specialization. Basically, the Array class template delegates creation of storage to another class template that is partially specialized on some magic value they've named Dynamic.
Here's a basic example:
#include <memory>
constexpr int Dynamic = -1;
template <typename T, int N>
struct Storage
{
Storage() : data{} {}
T data[N];
};
template <typename T>
struct Storage<T, Dynamic>
{
Storage(int count) : data{new T[count]} {}
Storage() = delete;
std::unique_ptr<T[]> data;
};
template <typename T, int N>
struct Array
{
Array() : storage{} {}
Array(int count) : storage{count} {}
Storage<T, N> storage;
};
int main() {
Array<int, 4> a1;
//Array<int, 4> a2(10); // Error since base Storage template has no constructor taking int.
Array<int, Dynamic> a3(10);
//Array<int, Dynamic> a4{}; // Error since Storage<T, Dynamic> has its default constructor deleted.
}
Live demo
Basically there are two different Storage templates, one that will be used when N == Dynamic and another that will be used for any other value.
In fact, if you look in DenseStorage.h you'll see a similar pattern to my example. There are a lot more specializations to support multiple dimensions and various differently-aligned data types, but it's the same concept.
I have tried union...
struct foo
{
union
{
struct // 2 bytes
{
char var0_1;
};
struct // 5 bytes
{
char var1_1;
int var1_2;
};
};
};
Problem: Unions do what I want, except they will always take the size of the biggest datatype. In my case I need struct foo to have some initialization that allows me to tell it which structure to chose of the two (if that is even legal) as shown below.
So after that, I tried class template overloading...
template <bool B>
class foo { }
template <>
class foo<true>
{
char var1;
}
template <>
class foo<false>
{
char var0;
int var1;
}
Problem: I was really happy with templates and the fact that I could use the same variable name on the char and int, but the problem was the syntax. Because the classes are created on compile-time, the template boolean variable needed to be a hardcoded constant, but in my case the boolean needs to be user-defined on runtime.
So I need something of the two "worlds." How can I achieve what I'm trying to do?
!!NOTE: The foo class/struct will later be inherited, therefore as already mentioned, size of foo is of utmost importance.
EDIT#1::
Application:
Basically this will be used to read/write (using a pointer as an interface) a specific data buffer and also allow me to create (new instance of the class/struct) the same data buffer. The variables you see above specify the length. If it's a smaller data buffer, the length is written in a char/byte. If it's a bigger data buffer, the first char/byte is null as a flag, and the int specifies the length instead. After the length it's obvious that the actual data follows, hence why the inheritance. Size of class is of the utmost importance. I need to have my cake and eat it too.
A layer of abstraction.
struct my_buffer_view{
std::size_t size()const{
if (!m_ptr)return 0;
if (*m_ptr)return *m_ptr;
return *reinterpret_cast<std::uint32_t const*>(m_ptr+1);
}
std::uint8_t const* data() const{
if(!m_ptr)return nullptr;
if(*m_ptr)return m_ptr+1;
return m_ptr+5;
}
std::uint8_t const* begin()const{return data();}
std::uint8_t const* end()const{return data()+size();}
my_buffer_view(std::uint_t const*ptr=nullptr):m_ptr(ptr){}
my_buffer_view(my_buffer_view const&)=default;
my_buffer_view& operator=(my_buffer_view const&)=default;
private:
std::uint8_t const* m_ptr=0;
};
No variable sized data anywhere. I coukd have used a union for size etx:
struct header{
std::uint8_t short_len;
union {
struct{
std::uint32_t long_len;
std::uint8_t long_buf[1];
}
struct {
std::short_buf[1];
}
} body;
};
but I just did pointer arithmetic instead.
Writing such a buffer to a bytestream is another problem entirely.
Your solution does not make sense. Think about your solution: you could define two independents classes: fooTrue and fooFalse with corresponding members exactly with the same result.
Probably, you are looking for a different solution as inheritance. For example, your fooTrue is baseFoo and your fooFalse is derivedFoo with as the previous one as base and extends it with another int member.
In this case, you have the polymorphism as the method to work in runtime.
You can't have your cake and eat it too.
The point of templates is that the specialisation happens at compile time. At run time, the size of the class is fixed (albeit, in an implementation-defined manner).
If you want the choice to be made at run time, then you can't use a mechanism that determines size at compile-time. You will need a mechanism that accommodates both possible needs. Practically, that means your base class will need to be large enough to contain all required members - which is essentially what is happening with your union based solution.
In reference to your "!!NOTE". What you are doing qualifies as premature optimisation. You are trying to optimise size of a base class without any evidence (e.g. measurement of memory usage) that the size difference is actually significant for your application (e.g. that it causes your application to exhaust available memory). The fact that something will be a base for a number of other classes is not sufficient, on its own, to worry about its size.
I'm currently not able to set up my class members like I want to. My templated class is only specialized for sensible integer types (unsigned and “small”). Each specialization needs a rather big look-up table that only depends on the type. So I thought it should definitely be static (and const) and created only once.
As C++ doesn't have static constructors I learned that you can create a class that does the heavy stuff on initialization and have that as a static member.
I reduced my code to these basics:
// Of this, I only want one instance per type,
// because the table can get big.
template<class T>
struct LookUp
{
static int const SIZE = 1 << (sizeof(T) << 3);
std::vector<T> table;
LookUp()
: table{ SIZE }
{
for (int i = 0; i < SIZE; ++i)
{
// Dummy code
table[i] = i;
}
}
};
// "Normal" template class with common code for all types.
template<class T>
class LbpHelper
{
typedef /*...*/ image;
};
// No functionality for the general case.
template<class T>
class Lbp
{
};
// But for this (among others) we have something.
template<>
class Lbp<uint8_t> : public LbpHelper<uint8_t>
{
typedef uint8_t value_type;
typedef Lbp::image image;
static LookUp<value_type> _lookup; // <-- This is the mean one.
public:
// Stuff...
};
Initializing static members seems to confuse a lot of users, especially when it comes to templates and specialization. I read quite some answers here but none of them solved my problem.
I tried having something like
// The type of the class is the same as the type of the member class.
template<> LookUp<uint8_t> Lbp<uint8_t>::_lookup{};
template<> LookUp<uint16_t> Lbp<uint16_t>::_lookup{};
in the header or the source file or both. I tried with or without a class T in the angle brackets (and using T to the right of course), leaving out the template<> alltogether, having the {}s only in the source — I don't know what else. Nothing worked.
Visual C++ either tells me that _lookup is not a member or that it is not an entity that can be specialized or this: error C2373: '_lookup' : redefinition; different type modifiers.
Can someone please tell me what to put where so that it compiles?
Just drop the template<> bit, and put the definition of the static data members in a .cpp file:
LookUp<uint8_t> Lbp<uint8_t>::_lookup{};
LookUp<uint16_t> Lbp<uint16_t>::_lookup{};
[Live example]
... and, since the type of _lookup is a class, you can leave out the {} as well; its default constructor will be called anyway. This might please VC++ if you're using a version which does not support uniform initialisation.
Why this is the proper way: template<> is used to introduce explicit specialisations. You're not introducing an explicit specialisation - you're defining a data member of an already defined explicit specialisation.
This is covered by C++11 14.7.3/5:
... Members of an explicitly specialized class template are
defined in the same manner as members of normal classes, and not using the template<> syntax. The same
is true when defining a member of an explicitly specialized member class. ...
I have a struct being used somewhere which is declared as:
struct Foo
{
someArray[64];
//...other stuff
};
It is used extensively in many places, and I would like to change it to this:
template <size_t N = 64>
struct Foo
{
someArray[N];
//...other stuff
};
because there is one place (well four to be exact) where this struct needs to be used with a 128 byte array for correctness, but the penalty it introduces for ALL the other uses is not worth paying. In providing a default template argument I was hoping it would go through transparently, except for those in the know-how who need a wider internal array which would then declare Foo<128>. Unfortunately, it seems to force every use of it to say Foo<>. Is there a way around this?
You cannot omit the angular brackets when instantiating a class template.
However, you can give a different name to your Foo class template (say, FooN) and then provide a type alias such as:
typedef FooN<> Foo;
This way, clients who were using the original, non-template version of Foo won't have to be changed, and clients that need the flexibility of overriding the default N can use the generic class template:
FooN<128> obj;
To answer the question first: No there isn't a way to use it without <>. However that doesn't mean you can't do something else to keep your codebase intact.
The easiest solution is to rename templated variant to something else and provide a Typedef for the name Foo:
template <size_t N = 64>
struct GenericFoo
{
someArray[N];
//...other stuff
};
typedef GenericFoo<64> Foo;
This way you can keep using Foo in all the other instances and have the option of using GenericFoo<Whatever> when you need fine grained control.
namespace generic
{
template <int N> class Foo {};
}
// user code
typedef generic::Foo<64> Foo; // common users
// OR
using generic::Foo; // rare users