Loop over POD members - c++

I'm wondering on how to properly loop over the members of a plain old data type, in order to get some type information on them. That is :
struct my_pod
{
int a;
double b;
};
template<typename POD>
void loopOverPOD()
{
for_each(POD, member) // The magic part
{
// member::type should be for my_pod int, then double
typename member::type i;
// member::size_of should be equal to sizeof(int) then sizeof(double)
// Trivial if we can have member::type information.
int size = member::size_of;
// member::offset_of should be equal to 0, then sizeof(int)
// Trivial if we can have member::size_of information.
int offset = member::offset_of;
}
}
As far as I know in C++, we can't do easy type introspection without doing some tricky plays with templates. But here, I can't find a concrete solution with templates, even with the use of macro in fact. And the problem is more about me rather than about the existence of a solution. :-)
I'm not necessarily asking for a solution that would not be intrusive.
Thanks in advance.

You could use boost.fusions ADAPT_STRUCT to turn your POD into a sequence and then use fusions for_each to apply a function object to each member. This is non-intrusive, your POD type will remain POD.
The good thing is that you could even put the ADAPT_STRUCT macros in a (header-) file separate from your struct definitions and only use them in code where you need to iterate.
The flip side is that this macro requires the redundancy of mentioning both the type and the name of the members again. I imagine that at some point fusion will use C++11 features to get rid of that redundancy (mentioning the type again). In the mean time, it is possible to create a macro that will declare the struct and the ADAP_STRUCT part.

If you use C++14 and newer, you can use Boost.Precise and Flat Reflection (https://github.com/apolukhin/magic_get/) for looping over your POD and boost::typeindex::type_id_runtime(field) to print type:
#include <iostream>
#include <boost/pfr/precise.hpp>
#include <boost/pfr/flat.hpp>
#include <boost/type_index.hpp>
struct my_pod
{
int a;
double b;
};
struct my_struct
{
char c;
my_pod pod;
};
int main() {
my_pod val{1, 2.5};
my_struct var{'a', 1, 2.5};
std::cout << "Flat:\n";
boost::pfr::flat_for_each_field(var, [](const auto& field, std::size_t idx) {
std::cout << idx << ": " << boost::typeindex::type_id_runtime(field) << "; value: " << field << '\n';
});
std::cout << "\nNot Flat:\n";
boost::pfr::for_each_field(var, [](const auto& field, std::size_t idx) {
using namespace boost::pfr::ops;
std::cout << idx << ": " << boost::typeindex::type_id_runtime(field) << "; value: " << field << '\n';
});
}
Output for this example:
Flat:
0: char; value: a
1: int; value: 1
2: double; value: 2.5
Not Flat:
0: char; value: a
1: my_pod; value: {1, 2.5}
Though I'm not sure how to get offset in this case...

C++ has no construct to iterate through members of a structure.
There exists however a standard type std::tuple for which you can use templates to recursively iterate through its elements at compile time.

Related

Why is basic_string_view not limited to character types?

Browsing twitter I found this example of C++23 code.
This is my adaptation of it, to make more obvious what I am interested about(I do not care about dangling problems mentioned in replies).
#include <vector>
#include <string_view>
#include <iostream>
#include <type_traits>
int main() {
std::vector v{84.72};
std::basic_string_view sv = v;
static_assert(std::is_same_v<decltype(sv), std::basic_string_view<double>>);
const auto val = *std::begin(sv);
std::cout << val;
}
My question is why isn't there some requires/concept constraint on the basic_string_view to make it work only with charish types, so basic_string_view<double> in this example would not compile?
I suspect that this is a char-like type:
struct Char {
char c;
Char() : c{} {}
Char(char c) : c{c} {}
};
Why shouldn't it work? Indeed it does
std::basic_string<Char> str{'a', 'b'}; // OK
std::cout << str[0].c << std::endl; // prints a
std::cout << str.length() << std::endl; // prints 2
And what makes that class special with respect to, say, this?
struct Char {
int c;
Char() : c{} {}
Char(int c) : c{c} {}
};
Nothing, except our decision that char is a character and int is not. (And that's exactly the reason why I had to write std::cout << str[0].c and couldn't write std::cout << str or std::cout << str[0], because << is overloaded for chars and maybe something else, but certainly not for my own types.)
So the bottom line, as implied by some comments, is a counter-question:
How would you define a "charish" type?
which I would rephrase as
Can we encode the definiton of "sequence of char-like objects" in a concept?
which leads in turn to another question:
What operations can you do only on a "sequence of char-like objects" that you can't do on all "sequences of non-char-like objects"?
I can't think of one.
So if you wanted to enforce the constraint you mention, you would end up explicitly listing char, wchar, and all the others in some SFINAE thing.
And then you couldn't use it with any other type.

What happens after C++ references are compiled?

After compilation, what does the reference become, an address, or a constant pointer?
I know the difference between pointers and references, but I want to know the difference between the underlying implementations.
int main()
{
int a = 1;
int &b = a;
int *ptr = &a;
cout << b << " " << *ptr << endl; // 1 1
cout << "&b: " << &b << endl; // 0x61fe0c
cout << "ptr: " << ptr << endl; // 0x61fe0c
return 0;
}
The pedantic answer is: Whatever the compiler feels like, all that matters is that it works as specified by the language's semantics.
To get the actual answer, you have to look at resulting assembly, or make heavy usage of Undefined Behavior. At that point, it becomes a compiler-specific question, not a "C++ in general" question
In practice, references that need to be stored essentially become pointers, while local references tend to get compiled out of existence. The later is generally the case because the guarantee that references never get reassigned means that if you can see it getting assigned, then you know full well what it refers to. However, you should not be relying on this for correctness purposes.
For the sake of completeness
It is possible to get some insight into what the compiler is doing from within valid code by memcpying the contents of a struct containing a reference into a char buffer:
#include <iostream>
#include <array>
#include <cstring>
struct X {
int& ref;
};
int main() {
constexpr std::size_t x_size = sizeof(X);
int val = 12;
X val_ref = {val};
std::array<unsigned char, x_size> raw ;
std::memcpy(&raw, &val_ref, x_size);
std::cout << &val << std::endl;
std::cout << "0x";
for(const unsigned char c : raw) {
std::cout << std::hex << (int)c;
}
std::cout << std::endl ;
}
When I ran this on my compiler, I got the (endian flipped) address of val stored within the struct.
it heavily depend on compiler maybe compiler decide to optimize the code therefore it will make it value or ..., but as far i know references will compiler like pointer i mean if you see their result assembly they are compiled like pointer.

How to access C++ struct property value using index?

struct student {
string name;
int age;
};
int main() {
student a1;
cout << a1[0] << endl; //Access the first variable of the struct
cout << a2[1] << endl; //Access the first variable of the struct
}
How could I access and retrieve value from the C++ struct using index instead of using "a1.name" ??
One way to do this is by creating a tuple from the member variables and using std::tie to get at the member by index. The index would have to be known at compile time however. You could wrap this inside a member function of your struct:
#include <tuple>
#include <iostream>
struct student {
std::string name;
int age;
template<size_t I>
auto& get() {
return std::get<I>(std::tie(name, age));
}
};
int main() {
student boy{ "Paul", 12 };
std::cout << "Name: " << boy.get<0>() << " Age: " << boy.get<1>() << std::endl;
//Change members
boy.get<0>() = "John";
boy.get<1>() = 14;
std::cout << "Name: " << boy.get<0>() << " Age: " << boy.get<1>() << std::endl;
}
Demo
(Requires at least C++14)
In C++11, since it doesn't have automatic return type deduction unless specified, you could use std::tuple_element to specify the return type instead:
#include <tuple>
#include <iostream>
struct student {
std::string name;
int age;
template<size_t I>
using T = typename std::tuple_element<I, std::tuple<std::string, int>>::type;
template<size_t I>
T<I>& get()
{
return std::get<I>(std::tie(name, age));
}
};
int main() {
student boy{ "Paul", 12 };
std::cout << "Name: " << boy.get<0>() << " Age: " << boy.get<1>() << std::endl;
//Change members
boy.get<0>() = "John";
boy.get<1>() = 14;
std::cout << "Name: " << boy.get<0>() << " Age: " << boy.get<1>() << std::endl;
}
Demo
You can't. At least not in the direct manner you want to do it and without partially redefining what a structure is. I will split my answer into two parts the first one explaining possible ways to get at least close to what you want and the second one explaining what you actually should do:
Getting down and dirty
There are two ways (that I can currently come up with) that might give you something to think about:
Use a wrapper class - while C++ does increase the flexibility of structure it doesn't change their purpose of a simple heterogeneous data container. It does however allow operator overloading including the [] operator. So if you create a class that contains the structure as its member (that is it wraps around the structure), you can expose the structure's data using []. This comes as close to what you want to do as possible. It does however defeat the whole purpose of using a struct since you can do that with just plain non-sturct class members but I have actually seen it not so long time ago when I was going through a C++ library that was wrapping a previous C-based version of itself in order to provide more modern features without the need of completely rewriting the C code.
Use pointer with an offset - using indexing generally suggest that the underlying container has a consistency when it comes to the blocks of data it contains. The problem is that a structure doesn't necessarily obey this since it can contain (just like in your case) multiple types of data. If you can sacrifice the heterogeneity of your structure and stick with a single data type (for example one or more doubles), you can safely use (up to the point that you have to always remember the number of members the structure has) a pointer and an increasing/decreasing offset to access its members. Just like with any sort of data when you create a standard reference (aka pointer) to something, that reference points at the address of the beginning of the memory this data is using. It is a common practice to use pointers to iterate through arrays and it works exactly like that - create a reference to your structure and the add +1, +2, ... (as many members that struct has). This makes things overly complicated though and is prone to error. As mentioned it also requires using the same type of data inside your structure. However you can also create a set of functions that handle (internally) the offsets. But this idea is similar to the class wrapper I have proposed above.
The alternatives ...
From what you have given as information I think you are looking for a completely different type of data - a dictionary, map or a list that contains some sort of custom generic data container that can hold any type of data but also stores that data's type in order to allow recasting it to its original state. Many libraries provide such containers for example Qt has the QVariant (part of the core module), boost has the boost::variant, std::tuple (or even better - named tuples) provided with your standard C++ (since C++11) and so on. I can speak about Qt in greater detail since I have more experience with it. It offers the QVariantList (a typedef for QList<QVariant>) which allows indexing. Of course all this requires you to 1)abandon your structure-thing and 2)use some more advanced containers that may or may not introduce huge drawbacks on whatever you are working on including licensing issues, memory overhead, larger binaries, handling a lot of extra library files etc.
How to access C++ struct property value using index?
You can not. C++ language has no feature that would allow this. This could be possible in a language that supports (static) reflection.
You could choose to use a std::tuple instead, which does allow indexed member access, but that's a step down in readability since you don't get to name the members.
I tried to stay as close to your example as possible but I did have to convert the age from int to string. This works and I have found it useful in one application.
struct student
{
std::string name, age;
std::string *elemtnPtr[10];
student()
{
int i=0;
elemtnPtr[i++] = &name;
elemtnPtr[i++] = &age;
}
};
void demo()
{
student a1;
a1.name = "This Works";
a1.age = "99";
std::cout << *a1.elemtnPtr[0] << std::endl;
std::cout << *a1.elemtnPtr[1] << std::endl;
}
You cannot.
Not until reflection has been introduced in C++, which should (I hope) be the case in C++20.
Some projects introduce tuples enhanced with names, but it still not real structs.

How can I store objects of differing types in a C++ container?

Is there a C++ container that I could use or build that can contain, say, int and string and double types? The problem I'm facing is that whenever I try to populate, say, a map, vector or list with, say, the following:
int x;
string y;
double z;
I'm restricted with the format:
list<int> mycountainer;
vector<string> mycontainer;
which forces mycontainer to only consist of one type.
Before anyone suggest generics, that wouldn't work either since the standard vector and list containers that come with C++ are already generic - they can be container for any types but cannot contain multiple types.
I would like to avoid using Boost also if at all possible - I'd prefer it if there is a simple way I could code this myself.
You could use (or re-implement) boost::any and store instances of boost::any in a container. That would be the safest, since boost::any has probably dealt with much of the edge cases and complexity involved in solving this kind of problem in the general case.
If you want to do something quick and dirty, create a structure or perhaps a union containing members of all potential types along with an enumeration or other indicator of which type is 'active' in the object. Be especially careful with unions as they have some interesting properties (such as invoking undefined behavior if you read the wrong union member, only one of the members can be 'active' at a time, the one that was most recently written to).
I'm curious what you're doing that you need such a construct, though.
Well, the first question would be: Why do you think you need to store objects of different, totally unrelated types in the same container? That seems fishy to me.
If I had the need, I'd look into boost::variant or boost::any.
What you want is called a "hetrogenious container". C++ doesn't technically support them in the STL, but Boost does.
Given that, I think you'll find your answer in this question: how-do-you-make-a-heterogeneous-boostmap
You can use either structures, or classes or std::pair.
[edit]
For classes and structs:
struct XYZ {
int x;
string y;
double z;
};
std::vector<XYZ> container;
XYZ el;
el.x = 10;
el.y = "asd";
el.z = 1.123;
container.push_back(el);
For std::pair:
#include <pair>
typedef std::pair<int, std::pair<string, double> > XYZ;
std::vector<XYZ> container;
container.push_back(std::make_pair(10, std::make_pair("asd", 1111.222)));
You could use a struct that contains all three.
struct Data
{
int intVal;
std::string stringVal;
double doubleVal;
};
Then you could just declare list mycontainer<Data> and use the appropriate value, provided you know what the value type is. If not, add an addition field to the struct that tells you which of the three data types is in use.
struct Data
{
enum DATATYPE { DT_INT, DT_STRING, DT_DOUBLE } type;
int intVal;
std::string stringVal;
double doubleVal;
};
If you're worried about memory usage, you could probably use a union, though I tend to avoid using them. It might be needless paranoia on my part though.
The simplest method is of course to define a struct or class that has members of each of the types you wish to store. Josh's answer suggests Boost.Any, which will hold pretty much anything. If you want to restrict values to only those of types int, double, and std::string, then the better choice would be Boost.Variant.
If you simply don't want to use Boost, then I suggest you get over your hang-ups and use it anyway. "Not Invented Here" is a self-destructive policy. But if you can't use Boost, then you can write your own variant class instead. Andrei Alexandrescu wrote a three-part series on that (part 1, part 2, part 3) a few years ago, and its design inspired the one Boost uses.
What I have for this question is not what I hoped would work. By what I think that you would like, is a container that stores multiple value types, that you can access at will.
However, as such, a container would have to specify what value it holds, so you could have a class with 500 data types in it, with a correlating constructor for each data type, however, that would be super memory inefficient.
Here is my proposed suggestion, I have worked on for a day, And I hope it meets your criteria:
#include <iostream>
#include <vector>
using namespace std;
enum class type: unsigned int {int_t, unsigned_int_t, string_t, double_t, float_t, bool_t, unipointer_t, vector_int_t, vector_unipointer_t};//just add item types here and in the switch statement to hold more void_ps in unipointer...
class unipointer {
void* obj;//the pointer to the data. any type of pointer.
type objtype;//the object type, kept as an enum class.
struct void_p {//template magic... ;D
void* void_ptr;
template<typename T>//when object is initialized, it converts the the void* pointer to the output value.
operator T() {
return reinterpret_cast<T&>(void_ptr);
}
void_p(void* val): void_ptr(val) {};
};
public:
unipointer(void_p ptr, type ptrtype) : obj(ptr), objtype(ptrtype) {}
type get_type(void) {//Once you call this function, you know the type of data stored, and can call other functions accordingly.
return objtype;
}
template<typename T>//With a temlate, get any value through a pointer to it.
T get_ptr(void){
return reinterpret_cast<T&>(obj);
}
template<typename T>//With a temlate, get any value, as an object
T get_object(void) {
return *get_ptr<T*>();
}
void_p get_auto_pointer(void) {//get any pointer to value, can't be assigned to "auto*"!
return unipointer::void_p(obj);
}
void_p get_auto_object(void) {//get any value, can't be assigned to "auto"!
return *(void_p*)get_auto_pointer();
}
};
void process_stuff(unipointer& thing, unsigned int num_of_tabs);
int main() {
double initialization = 1.2345;
float even_another = 3.14159f;
unipointer items(new vector<unipointer>{//one thicc object instance
//Initialization examles:
unipointer(new int(-12345), type::int_t),
unipointer(new unsigned int(4'294'967'295), type::unsigned_int_t),
unipointer(new string("That is how I store my items."), type::string_t),
unipointer(&initialization, type::double_t),
unipointer(&even_another, type::float_t),
unipointer(new bool(1), type::bool_t),
unipointer(new unipointer(new unipointer(new unipointer(new string("OMG! NESTING!"), type::string_t), type::unipointer_t), type::unipointer_t), type::unipointer_t),
unipointer(new vector<int>{ 1,2,3 }, type::vector_int_t),
unipointer(new vector<unipointer>{
unipointer(new string("That is how I store my nested items."), type::string_t),
unipointer(new vector<int>{4,5,6}, type::vector_int_t),
unipointer(new string("Is your head brimming with ideas yet?"), type::string_t)
} , type::vector_unipointer_t)
}, type::vector_unipointer_t);
cout << "What is in the \"items\" unipointer:" << endl;
process_stuff(items, 1);
system("pause");
}
void process_stuff(unipointer& thing, unsigned int num_of_tabs) {
//declare variables & lamda for interpretaion methods, using variable assignment with "get auto object/pointer"
unsigned int* test = 0;
double test_2 = 0;
auto tab_to_current = [num_of_tabs]() {
for (unsigned int i = 0; i < num_of_tabs; ++i) {
cout << "\t";
}
};
//format the thing.
tab_to_current();
//look through and do stuff
switch (thing.get_type()) {//just add item types here and in the enum class to hold more void_ps in unipointer...
case type::int_t:
cout << "The integer: " << *thing.get_ptr<int*>() << "." << endl;//one way of getting object back from class
break;
case type::string_t:
cout << "The string: \"" << thing.get_object<string>() << "\"." << endl;//another way
break;
case type::unsigned_int_t:
test = thing.get_auto_pointer();//another way
cout << "The unsigned integer: " << *test << "." << endl;//don't forget to de-reference it!
delete test;
break;
case type::double_t:
test_2 = thing.get_auto_object();
cout << "The double: " << test_2 << "." << endl;//even another way!
break;
case type::float_t:
cout << "The float: " << float(thing.get_auto_object()) << "." << endl;//even another way!
break;
case type::bool_t:
cout << "The boolean: " << *(bool*)thing.get_auto_pointer() << "." << endl;//even another way!
break;
case type::unipointer_t:
cout << "A unipointer, and in it:" << endl;
process_stuff(*&thing.get_object<unipointer>(), num_of_tabs+1);
tab_to_current();
cout << "[End of unipointer]" << endl;
break;
case type::vector_int_t:
cout << "A vector of integers, and in it:" << endl;
for (unsigned int i = 0; i < thing.get_object<vector<int>>().size(); ++i) {
tab_to_current();
cout << "\tItem " << i << ": " << thing.get_object<vector<int>>().at(i) << endl;
}
tab_to_current();
cout << "[End of vector of integers]" << endl;
break;
case type::vector_unipointer_t:
cout << "A vector of unipointers, and in it:" << endl;
for (unsigned int i = 0; i < thing.get_object<vector<unipointer>>().size(); ++i) {
process_stuff(*&thing.get_object<vector<unipointer>>().at(i), num_of_tabs + 1);
}
tab_to_current();
cout << "[End of unipointer vector]" << endl;
break;
}
}
The "unipointer" class should be initialized with a pointer to any object type, and also the type of object. The class can return, through a function, your data, although it is not very safe, and could be called with the wrong type of data.
This is just an example of what could work, I sure hope that you take inspiration from it.
And, to answer your original question, you would set up a list, or vector with the following format:
vector/list:
|
|unipointer(*double)
|
|unipointer(*int)
|
|unipointer(*string)
|
...
|
end
PS: I am a beginner with objects and templates, so this might be messy. Many apoligies.
If you have a finite number of items you need to store, put them in a class or structure.
If there is no limit to the items you would need to store in this container then look at a different way of doing things because the only way of doing it is by storing them as an object, and then casting them to their own type when you need to access them.
However, if any item could potentially be in the container, then you have no way of knowing what type specific items in the container are, and therefore will not be able to cast them.
If C++ contained reflection, there would possibly be a way to do this, but C++ doesn't have reflection.

Can I define a type based on the result of some calculation?

I perform some calculations, based on the result, I would like to either use a short int or int for some type of data for the remaining program. Can (/How can) this be done sensibly in C or C++? I don't really care about the amount of memory used (i.e., 2 or 4 bytes), my primary aim is to access generic arrays as if they contained data of this type. I would like to avoid code such as the following:
char s[128];
if (result of preliminary calculations was A)
*((int*) s) = 50;
else
*((short int*) s) = 50;
to set the first 4 or 2 bytes of s. A conditional global typedef would be ideal:
if (result of preliminary calculations was A)
typedef int mytype;
else
typedef short int mytype;
I am not that familiar with C++ class templates (yet). Do they apply to my problem? Would I have to change the declarations throughout my program (to myclass< > and myclass< >*)?
Many thanks!
Frank
Edit: The values may not always be aligned. I.e, a int can start at position 21. Thanks for the answers.
For plain C, you could do this using function pointers:
static union { s_int[32]; s_short[64]; s_char[128]; } s;
static void set_s_int(int i, int n)
{
s.s_int[i] = n;
}
static int get_s_int(int i)
{
return s.s_int[i];
}
static void set_s_short(int i, int n)
{
s.s_short[i] = n;
}
static int get_s_short(int i)
{
return s.s_short[i];
}
static void (*set_s)(int, int);
static int (*get_s)(int);
Set them once based on the preliminary calculations:
if (result of preliminary calculations was A)
{
set_s = set_s_int;
get_s = get_s_int;
}
else
{
set_s = set_s_short;
get_s = get_s_short;
}
Then just use the function pointers in the rest of the program:
set_s(0, 50); /* Set entry 0 in array to 50 */
Your file writing function can directly reference s or s.s_char depending on how it works.
In C and C++, all type information is defined at Compile-time. So no, you cannot do this.
If the result of the preliminary calculations can be found at compile time, then this can work. Here are some simple examples to show how this can work. To do more complicated examples, see http://en.wikipedia.org/wiki/Template_metaprogramming
using namespace std;
#include <iostream>
template<int x> struct OddOrEven { typedef typename OddOrEven<x-2>::t t; };
template<> struct OddOrEven<0> { typedef short t; };
template<> struct OddOrEven<1> { typedef int t; };
template<bool makeMeAnInt> struct X { typedef short t; };
template<> struct X<true> { typedef int t; };
int main(void) {
cout << sizeof(X<false>::t) << endl;
cout << sizeof(X<true>::t) << endl;
cout << sizeof(OddOrEven<0>::t) << endl;
cout << sizeof(OddOrEven<1>::t) << endl;
cout << sizeof(OddOrEven<2>::t) << endl;
cout << sizeof(OddOrEven<3>::t) << endl;
cout << sizeof(OddOrEven<4>::t) << endl;
cout << sizeof(OddOrEven<5>::t) << endl;
}
I think above is standard C++, but if not I can tell you this work on g++ (Debian 4.3.2-1.1) 4.3.2
I think your main problem is how you plan to read the data from s later on if you don't know what type to read.
If you have that part covered, you can use a union:
union myintegers
{
int ints[32];
short shorts[64];
};
Now simply use the type you want.
myintegers s;
if (result of preliminary calculations was A)
s.ints[0] = 50;
else
s.shorts[0] = 50;
As a step further, you could wrap it all in a class which is constructed with result of preliminary calculations was A and overrides the operators * and [] to store in one or the other.
But are you sure you want any of that?
In current C++ standard (C++03), you can't.
In fact you can use some advanced metaprogramming tricks but it will not help most of the time.
In the next standard (C++0x, certainly C++11 in the end), you will be able to use the keyword decltype to get the type of an expression. If you're using VC10 (VS2010) or GCC 4.4 or more recent, then you already have the feature available.
You could abuse templates for this purpose. Any code that's subject to the decision would have to be templated based on the int type. One branch would instantiate the int version, the other would instantiate the short int version. This is probably a bad idea*.
Edit
*Well, it's only a bad idea to apply this to your overall architecture. If you have a particular data type that encapsulates the varied behavior, a template should work just fine.
Here's a variation on Aaron McDaid's answer to illustrate it's use with conditions:
#include <iostream>
#include <string>
using namespace std;
template<int x> struct OddOrEven { typedef typename OddOrEven<x-2>::t t; };
template<> struct OddOrEven<0> { typedef short t; };
template<> struct OddOrEven<1> { typedef int t; };
int main() {
cout << "int or short? ";
string which;
cin >> which;
if (which.compare("int") == 0)
cout << sizeof(OddOrEven<1>::t) << endl;
else if (which.compare("short") == 0)
cout << sizeof(OddOrEven<0>::t) << endl;
else
cout << "Please answer with either int or short next time." << endl;
return 0;
}
This is a code snippet from a project I had a while back.
void* m_pdata;
if (e_data_type == eU8C1){
pimage_data = new unsigned char[size_x * size_y];
}
if (e_data_type == eU16C1){
pimage_data = new unsigned short[size_x * size_y];
}
I hope it can help you
Since your stated goal is to store information efficiently on disk, you should learn to stop writing memory images of C/C++ data structures to disk directly and instead serialize your data. Then you can use any of a number of forms of variable-length coding ("vlc") to get the effect you want. The simplest is a coding with 7 bits per byte where the 8th bit is a continuation flag indicating that the value is continued in the next byte. So 259 would be stored as (binary, with continuation bit marked by spacing and byte boundaries marked by ;):
1 0000010 ; 0 0000011
Alternatively you could use the head nibble to signal the number of bytes that will follow, or use a scheme similar to UTF-8 with slightly more overhead but stricter resynchronization guarantees. There are also vlcs with are designed to be parsable and easily resynchronized when reading either forward or in reverse.