Is there a general way to check for an overflow or an underflow of a given data type (uint32, int etc.)?
I am doing something like this:
uint32 a,b,c;
... //initialize a,b,c
if(b < c) {
a -= (c - b)
}
When I print a after some iterations, it displays a large number like: 4294963846.
To check for over/underflow in arithmetic check the result compared to the original values.
uint32 a,b;
//assign values
uint32 result = a + b;
if (result < a) {
//Overflow
}
For your specific the check would be:
if (a > (c-b)) {
//Underflow
}
I guess if I wanted to do that I would make a class that simulates the data type, and do it manually (which would be slow I would imagine)
class MyInt
{
int val;
MyInt(const int&nval){ val = nval;} // cast from int
operator int(){return val;} // cast to int
// then just overload ALL the operators... putting your check in
};
//typedef int sint32;
typedef MyInt sint32;
it can be more tricky than that, you might have to wind up using a define instead of a typedef...
I did a similar thing with pointers to check where memory was being written out side of bounds. very slow but did find where memory was being corrupted
Cert has a good reference for both signed integer overflow which is undefined behavior and unsigned wrapping which is not and they cover all the operators.
The document provides the following checking code for unsigned wrapping in subtraction using preconditions is as follows:
void func(unsigned int ui_a, unsigned int ui_b) {
unsigned int udiff;
if (ui_a < ui_b){
/* Handle error */
} else {
udiff = ui_a - ui_b;
}
/* ... */
}
and with post-conditions:
void func(unsigned int ui_a, unsigned int ui_b) {
unsigned int udiff = ui_a - ui_b;
if (udiff > ui_a) {
/* Handle error */
}
/* ... */
}
If you are gcc 5 you can use __builtin_sub_overflow:
__builtin_sub_overflow( ui_a, ui_b, &udiff )
Boost has a neat library called Safe Numerics. Depending on how you instantiate the safe template, the library will throw an exception when overflow or underflow has occurred. See https://www.boost.org/doc/libs/1_74_0/libs/safe_numerics/doc/html/index.html.
I'll put here another possible approach in case a bigger (x2 size) integer type is available. In that case it is possible to prevent the overflow from happening at the expense of a little more computation.
// https://gcc.godbolt.org/z/fh9G6Eeah
#include <exception>
#include <limits>
#include <iostream>
using integer_t = uint32_t; // The desired type
using bigger_t = uint64_t; // Bigger type
constexpr integer_t add(const integer_t a, const integer_t b)
{
static_assert(sizeof(bigger_t)>=2*sizeof(integer_t));
constexpr bigger_t SUP = std::numeric_limits<integer_t>::max();
constexpr bigger_t INF = std::numeric_limits<integer_t>::min();
// Using larger type for operation
bigger_t res = static_cast<bigger_t>(a) + static_cast<bigger_t>(b);
// Check overflows
if(res>SUP) throw std::overflow_error("res too big");
else if(res<INF) throw std::overflow_error("res too small");
// Back to the original type
return static_cast<integer_t>(res); // No danger of narrowing here
}
//---------------------------------------------------------------------------
int main()
{
std::cout << add(100,1) << '\n';
std::cout << add(std::numeric_limits<integer_t>::max(),1) << '\n';
}
Related
I am sure this question has been asked already but I couldn't find the answer.
If I have a function, let's say:
int Power(int number, int degree){
if(degree==0){
return 1;
}
return number*Power(number, degree-1);
}
It works only when the degree is a non-negative int. How can I prevent this function from being called with wrong parameters?
For example, if the programmer writes cout<<Power(2, -1);, I want the compiler to refuse to compile the code and return some kind of an error message (e.g. "function Power accepts only non-negative integers").
Another alternative would be for the function to not return any value in this case. For example:
int Power(int number, unsigned int degree){
if(degree<0){
//return nothing
}
if(degree==0){
return 1;
}
return number*Power(number, degree-1);
}
There is an alternative to returning a value: Throw a value. A typical example:
if(degree<0){
throw std::invalid_argument("degree may not be negative!");
}
I want the compiler to refuse to compilate the code
In general, arguments are unknown until runtime, so this is not typically possible.
Your answer does the job for menicely. But I am curious: 'throw' terminates the program and prevents anything after Power() to be executed.
If you catch the thrown object, then you can continue immediately after the function from which the object was thrown.
The mere fact, that C++ does implicit type conversions, leaves you no way out of the predicament, that if you write unsigned int x = -1;, no matter which warnings you turn on with your compiler, you won't see any problem with that.
The only rule coming to mind, which might help you with that, is the notorious "max zero or one implicit conversions" rule. But I doubt it can be exploited in this case. (-1 would need to be converted to unsigned int, then to another type, implicitly). But I think from what I read on the page I linked above, numeric implicit conversions do not really count under some circumstances.
This leaves you but one other, also imperfect option. In the code below, I outline the basic idea. But there is endless room to refine the idea (more on that, later). This option is to resort to optional types in combination with your own integer type. The code below also only hints to what is possible. All that could be done in some fancy monadic framework or whatnot...
Obviously, in the code, posted in the question, it is a bad idea to have argument degree as an unsigned int, because then, a negative value gets implicitly converted and the function cannot protect itself from the hostile degree 0xFFFFFFFF (max value of unsigned int). If it wanted to check, it had better chosen int. Then it could check for negative values.
The code in the question also calls for a stack overflow, given it does not implement power in a tail recursive way. But this is just an aside and not subject to the question at hand. Let's get that one quickly out of the way.
// This version at least has a chance to benefit from tail call optimizations.
int internalPower_1 (int acc, int number, int degree) {
if (1 == degree)
return acc * number;
return internalPower_1(acc*number, number, degree - 1);
}
int Power_1 (int number, int degree) {
if (degree < 0)
throw std::invalid_argument("degree < 0");
return internalPower_1( 1, number, degree);
}
Now, would it not be nice if we could have integer types, which depended on the valid value range? Other languages have it (e.g. Common Lisp). Unless there is already something in boost (I did not check), we have to roll such a thing ourselves.
Code first, excuses later:
#include <iostream>
#include <stdexcept>
#include <limits>
#include <optional>
#include <string>
template <int MINVAL= std::numeric_limits<int>::min(),
int MAXVAL = std::numeric_limits<int>::max()>
struct Integer
{
int value;
static constexpr int MinValue() {
return MINVAL; }
static constexpr int MaxValue() {
return MAXVAL; }
using Class_t = Integer<MINVAL,MAXVAL>;
using Maybe_t = std::optional<Class_t>;
// Values passed in during run time get handled
// and punished at run time.
// No way to work around this, because we are
// feeding our thing of beauty from the nasty
// outside world.
explicit Integer (int v)
: value{v}
{
if (v < MINVAL || v > MAXVAL)
throw std::invalid_argument("Value out of range.");
}
static Maybe_t Init (int v) {
if (v < MINVAL || v > MAXVAL) {
return std::nullopt;
}
return Maybe_t(v);
}
};
using UInt = Integer<0>;
using Int = Integer<>;
std::ostream& operator<< (std::ostream& os,
const typename Int::Maybe_t & v) {
if (v) {
os << v->value;
} else {
os << std::string("NIL");
}
return os;
}
template <class T>
auto operator* (const T& x,
const T& y)
-> T {
if (x && y)
return T::value_type::Init(x->value * y->value);
return std::nullopt;
}
Int::Maybe_t internalPower_3 (const Int::Maybe_t& acc,
const Int::Maybe_t& number,
const UInt::Maybe_t& degree) {
if (!acc) return std::nullopt;
if (!degree) return std::nullopt;
if (1 == degree->value) {
return Int::Init(acc->value * number->value);
}
return internalPower_3(acc * number,
number,
UInt::Init(degree->value - 1));
}
Int::Maybe_t Power_3 (const Int::Maybe_t& number,
const UInt::Maybe_t& degree) {
if (!number) return std::nullopt;
return internalPower_3 (Int::Init(1),
number,
degree);
}
int main (int argc, const char* argv[]) {
std::cout << Power_1 (2, 3) << std::endl;
std::cout << Power_3 (Int::Init(2),
UInt::Init(3)) << std::endl;
std::cout << Power_3 (Int::Init(2),
UInt::Init(-2)) << std::endl;
std::cout << "UInt min value = "
<< UInt::MinValue() << std::endl
<< "Uint max value = "
<< UInt::MaxValue() << std::endl;
return 0;
}
The key here is, that the function Int::Init() returns Int::Maybe_t. Thus, before the error can propagate, the user gets a std::nullopt very early, if they try to init with a value which is out of range. Using the constructor of Int, instead would result in an exception.
In order for the code to be able to check, both signed and unsigned instances of the template (e.g. Integer<-10,10> or Integer<0,20>) use a signed int as storage, thus being able to check for invalid values, sneaking in via implicit type conversions. At the expense, that our unsigned on a 32 bit system would be only 31 bit...
What this code does not show, but which could be nice, is the idea, that the resulting type of an operation with two (different instances of) Integers, could be yet another different instance of Integer. Example: auto x = Integer<0,5>::Init(3) - Integer<0,5>::Init(5) In our current implementation, this would result in a nullopt, preserving the type Integer<0,5>. In a maybe better world, though it would as well be possible, that the result would be an Integer<-2,5>.
Anyway, as it is, some might find my little Integer<,> experiment interesting. After all, using types to be more expressive is good, right? If you write a function like typename Integer<-10,0>::Maybe_t foo(Integer<0,5>::Maybe_t x) is quite self explaining as to which range of values are valid for x.
I'm using a C library that uses unsigned integers as index to some data. But sometimes, functions return those indices as signed in order to return -1 if the function fails to return an index.*
How do I prevent implicit conversion changes signedness warnings and instead, throw runtime errors if the conversion isn't possible? Would you recommend to wrap library functions to use exceptions for error handling and only return proper values?
Is there a standard way to do this:
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
// pointless c function to demonstrate the question
// parse the string to an unsigned integer, return -1 on failure
int atoui(char const* str) {
char* pend;
long int li=strtol(str, &pend, 10);
if ( errno!=0 || *pend!='\0' || li<0 || li>INT_MAX ) {
return -1;
} else {
return li;
}
}
// --8<---
#include <stdexcept>
// How to do this properly?
unsigned int unsign(int i) {
if(i<0) {
throw std::runtime_error("Tried to cast negative int to unsigned int");
} else {
return static_cast<unsigned>(i);
}
}
int main() {
unsigned int j=unsign(atoui("42")); // OK
unsigned int k=unsign(atoui("-7")); // Runtime error
}
The standard library has no such function, but it's easy enough to write such a template:
template<typename SInt, typename = std::enable_if_t<std::is_integeral_v<SInt> && std::is_signed_v<SInt>>>
constexpr auto unsigned_cast(Sint i)
{
if(i < 0) throw std::domain_error("Outside of domain");
return static_cast<std::make_unsigned_t<SInt>>(i);
}
You can also return an optional if you don't like throwing exceptions for such trivial matters:
template<typename SInt, typename = std::enable_if_t<std::is_integeral_v<SInt> && std::is_signed_v<SInt>>>
constexpr std::optional<std::make_unsigned_t<SInt>> unsigned_cast_opt(Sint i)
{
if(i < 0) return std::nullopt;
return static_cast<std::make_unsigned_t<SInt>>(i);
}
If you want a range check at runtime (i.e. permitting the conversion between types iff the value held can be maintained), Boost has numeric_cast that achieves this.
And if you don't want to use Boost, your approach looks decent enough.
Edit: I missed that you were using C++, my previous answer assumed C only.
The simplest and most standard way is to use
std::optional<unsigned int> index;
instead of using -1 or some other sentinel value to represent invalid index. If the index is invalid, you just don't set the optional. Then you can query it with
index.has_value()
to find out if it is valid or not.
I'm developing a generic Genetic Algorithm library, where the chromosome of each organism is its bit representation in memory. So, for instance, if I want to mutate a organism, I flip the bits themselves of the object randomly.
At first, I tried using the bitset class from the C++ standard library, but, when converting back to an object T, my only option was using the to_ullong member function, which was a problem for representations with a number of bits larger than the size of an unsigned long long.
Then I decided to create a generic library for bitwise operations on any object T, so I could apply these operations directly onto the objects themselves, instead of converting them first to a bitset.
So you can see what I'm trying to achieve, here's a function from the library:
template<typename T>
void flip(T& x, size_t const i)
{
x ^= 1 << i;
}
And it's used in the GA library like this:
template<typename T>
void GeneticAlgorithm<T>::mutate(T& organism, double const rate)
{
std::random_device rd;
std::mt19937 mt(rd());
std::uniform_real_distribution<double> dist(0, 1);
for(size_t i = 0; i < m_nBits; ++i)
if(dist(mt) <= rate)
bit::flip(organism, i);
}
It would be really nice if this worked, however now I'm getting this error message from the VC++ 2015 RC compiler:
Severity Code Description Project File Line Error C2677 binary '^': no
global operator found which takes type 'T' (or there is no acceptable
conversion) GeneticAlgorithm path\geneticalgorithm\geneticalgorithm\BitManip.hpp 57
If I correct this error for the ^, I get more for the other operators.
I haven't used bitwise operators before in my code, so I guess these operators are not supposed to be used with any object? If so, how could I work around the problem?
What you want to achieve can be done like that (see Peter Schneider's comment):
template<typename T> void flip(T& x, size_t const i) {
unsigned char* data = reinterpret_cast<unsigned char*>(&x);
data[i/8] ^= (1 << (i%8));
}
what it does is reinterpreting your data x as an array of bytes (unsigned char), then determining which byte should be flipped (i/8), then which bit within the byte (i%8).
Note: in addition, it may be safe to add at the beginning of the function:
assert(i < sizeof(T)*8)
I am under the impression that you are not yet fully appreciating the object oriented features C++ offers. (That's not untypical when coming from a more data-centric programming in C. C++ is specifically designed to make that transition at the desired speed and to make it painless.)
My suggestion is to encapsulate the flip operation in an organism and let the organism handle it. As an illustration (untested, but compiles):
#include<climits> // CHAR_BIT
#include<cstdlib> // exit()
class string;
void log(const char *);
// inaccessible from the outside
constexpr int NUM_TRAITS = 1000;
constexpr size_t TRAIT_ARR_SZ = (NUM_TRAITS+CHAR_BIT-1)/CHAR_BIT;
class Organism
{
char traits[TRAIT_ARR_SZ];
int flips[NUM_TRAITS];
/////////////////////////////////////////////////////////////
public:
Organism() { /* set traits and flips zero */ }
// Consider a virtual function if you may derive
/** Invert the trait at index traitIndex */
void flipTrait(int traitIndex)
{
if( traitIndex >= NUM_TRAITS ) { log("trait overflow"); exit(1); }
int charInd = traitIndex / CHAR_BIT;
int bitInd = traitIndex % CHAR_BIT;
traits[traitIndex] ^= 1 << bitInd;
flips[traitIndex]++;
}
// Organisms can do so much more!
void display();
void store(string &path);
void load(string &path);
void mutate(float traitRatio);
Organism clone();
};
For a project I have to implement a bitset class. My code thus far is:
Header File
#ifndef BITSET_H_
#define BITSET_H_
#include <string>
#include <cmath>
using namespace std;
// Container class to hold and manipulate bitsets
class Bitset {
public:
Bitset();
Bitset(const string);
~Bitset();
// Returns the size of the bitset
int size();
// Sets a bitset equal to the specified value
void operator= (const string);
// Accesses a specific bit from the bitset
bool operator[] (const int) const;
private:
unsigned char *bitset;
int set_size;
// Sets a bitset equal to the specified value
void assign(const string);
};
#endif /* BITSET_H_ */
Source File
#include "bitset.h"
Bitset::Bitset() {
bitset = NULL;
}
Bitset::Bitset(const string value) {
bitset = NULL;
assign(value);
}
Bitset::~Bitset() {
if (bitset != NULL) {
delete[] bitset;
}
}
int Bitset::size() {
return set_size;
}
void Bitset::operator= (const string value) {
assign(value);
}
bool Bitset::operator[] (const int index) const {
int offset;
if (index >= set_size) {
return false;
}
offset = (int) index/sizeof(unsigned char);
return (bitset[offset] >> (index - offset*sizeof(unsigned char))) & 1;
}
void Bitset::assign(const string value) {
int i, offset;
if (bitset != NULL) {
delete[] bitset;
}
bitset = new unsigned char[(int) ceil(value.length()/sizeof(unsigned char))];
for (i = 0; i < value.length(); i++) {
offset = (int) i/sizeof(unsigned char);
if (value[i] == '1') {
bitset[offset] |= (1 << (i - offset*sizeof(unsigned char)));
} else {
bitset[offset] &= ~(1 << (i - offset*sizeof(unsigned char)));
}
}
set_size = value.length();
}
My problem is my delete statements in both the deconstructor and assign method core dump. Is it not necessary to deallocate this memory? From what I've read so far it's always necessary to use the delete command whenever you call new.
EDIT: I've changed the code above to reflect one of the fixes. I added bitset = NULL in the constructor. This fixed the core dump in the assign method however I'm still getting errors in the deconstructor.
I think you should initialize bitset to NULL in your second constructor.
Why?
Because a pointer variable won't necessarily be initialized to NULL. So you may be trying to delete[] some random memory address when you use that second constructor.
So you should have:
Bitset::Bitset(const string value) : bitset(NULL)
{
assign(value);
}
Most likely you're copying a Bitset somewhere. You have not defined a copy constructor, not a copy assignment operator. The result of copying is then that you have two instances who both think they should deallocate the dynamically allocated array when they finish.
This is known as the Rule of Three: if you define any of destructor, copy constructor or copy assignment operator, then chances are that you'll need to define all three.
Now, about your code:
#include "bitset.h"
OK.
Bitset::Bitset() {
bitset = NULL;
}
(1) You didn't include a header that guaranteed defines NULL.
(2) you're not initializing the member set_size, so the check in the index operator may/will be using an indeterminate value, with Undefined Behavior.
(3) generally prefer to use initializer list rather than assignment (this avoids e.g. doing default construction followed by assignment).
Bitset::Bitset(const string value) {
bitset = NULL;
assign(value);
}
(4) Generally it's not a good idea to express construction in terms of assignment. Instead, express assignment in terms of construction.
Bitset::~Bitset() {
if (bitset != NULL) {
delete[] bitset;
}
}
(5) The check for NULL is unnecessary; you can safely delete a nullpointer.
int Bitset::size() {
return set_size;
}
(6) Uh, well, set_size was the member that wasn't initialized… Also, this member function should be const.
void Bitset::operator= (const string value) {
assign(value);
}
(7) An assignment operator should in general return a reference to the assigned-to object. That's just a convention, but it's what users of your class expect.
(8) Pass an in-argument by value or by reference to const. Generally, for built-in types choose by-value and for other types, such as std::string, choose reference to const. That is, the formal argument should better be string const& value.
bool Bitset::operator[] (const int index) const {
int offset;
if (index >= set_size) {
return false;
}
offset = (int) index/sizeof(unsigned char);
return (bitset[offset] >> (index - offset*sizeof(unsigned char))) & 1;
}
(9) First, again, the uninitialized set_size member.
(10) Then, note that sizeof(unsigned char) is 1 by definition. You probably want to use CHAR_BIT from <limits.h> here. Or just use 8 unless you plan on supporting Unisys computers (9-bit byte) or perhaps a Texas Instruments digital signal processor (16-bit byte).
void Bitset::assign(const string value) {
int i, offset;
if (bitset != NULL) {
delete[] bitset;
}
(11) The check for NULL is unnecessary.
bitset = new unsigned char[(int) ceil(value.length()/sizeof(unsigned char))];
(12) As already mentioned, sizeof(char) is 1 by definition.
(13) The division has integer arguments and so is an integer division, not a floating point division. Presumably what you want is the trick (a+b-1)/b?
for (i = 0; i < value.length(); i++) {
(14) Style: declare a variable as close to its first use as practically possible. Here it means declare the loop counter i directly in the loop head, like this: for( int i = 0, ....
offset = (int) i/sizeof(unsigned char);
(14) And ditto for offset. But for this variable you're not planning on changing its value, so also declare it const.
if (value[i] == '1') {
bitset[offset] |= (1 << (i - offset*sizeof(unsigned char)));
} else {
bitset[offset] &= ~(1 << (i - offset*sizeof(unsigned char)));
}
(15) Better rethink those shift operations!
}
set_size = value.length();
}
Cheers & hth.,
Make sure that the allocation size isn't zero, I suspect that's what's going on here, and that you're just writing to unallocated garbage memory. Running under valgrind will catch this too.
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.