I'm trying to implement a simple vector-swizzling functionality as a pet project to get into template metaprogramming. With the help of open-source mathematics library glm and some other posts on SO, I have come up with a solution which is basically working but has one error.
I have implemenented several structs which hold the data I need to represent a two dimensional eucledian vector. The struct "vec2" has a union which holds a float array with two elements (float data[2]) and two instances of struct "scalarSwizzle" which is supposed to implement the swizzling mechanic which allows me to acces the vector like so vec.data[0] or so vec.x.
Following the code I implemented so far:
#include <iostream>
template<typename T>
void print(T value)
{
std::cout << "print func: " << value << std::endl;
}
template<typename T, unsigned int I>
struct scalarSwiz
{
T value[1];
T &operator=(const T newValue)
{
value[I] = newValue;
return value[I];
}
operator T()
{
return value[I];
}
};
template<typename T>
struct vec2
{
union
{
T data[2];
scalarSwiz<T, 0> x;
scalarSwiz<T, 1> y;
};
vec2()
{
x = 0.0f;
y = 1.0f;
}
vec2(T pA, T pB)
{
x = pA;
y = pB;
}
};
int main(int argc, char *args[])
{
vec2<float> vec1{5.0f, 1.0f};
std::cout << "value vec1.data[0]: " << vec1.data[0] << std::endl;
std::cout << "value vec1.data[1]: " << vec1.data[1] << std::endl;
std::cout << "value vec1.x: " << vec1.x << std::endl;
std::cout << "value vec1.y: " << vec1.y << std::endl << std::endl;
print(vec1.data[0]);
print(vec1.data[1]);
print(vec1.x);
print(vec1.y);
std::cin.get();
}
The output is the following:
value vec1.data[0]: 5
value vec1.data[1]: 567.4
value vec1.x: 5
value vec1.y: 567.4
print func: 5
print func: 567.4
print func: 5
print func: 2.5565e-39
I expected the output to be the same for both printing the values directly in main() and via print() but vec.y is not resolved when I print it via the print() function. So I guess something is wrong with the overloaded typecast operator in "scalarSwizzle" but i have no idea what.
What I also dont understand is, why visual studio also doesn't resolve the value properly as seen on the following image:
vec1.y seem to be pointing to the same physical address then vec.x, while the direct std::cout in main() works fine.
I've been trying for a couple of days now to wrap my head around the problem, why the overloaded typecast operator doesnt work for vec.y but i just dont get it. Maybe someone here can help my with this problem.
Thank you!
First of all
template<typename T, unsigned int I>
struct scalarSwiz
{
T value[1];
T &operator=(const T newValue)
{
value[I] = newValue;
return value[I];
}
operator T()
{
return value[I];
}
};
results in undefined behavior if I != 0 (array access out of bounds) so don't expect your code to be correct or even stable.
Secondly, accessing an inactive member of a union is also undefined behavior (as per c++ standard). However, msvc, gcc and clang extend the c++ standard so that accessing inactive member behaves like we expect it to.
And finally, your scalarSwiz type can be replaced by an anonymous struct:
template<typename T>
struct vec2
{
union
{
T data[2];
struct
{
T x, y;
};
};
vec2()
{
x = 0.0f;
y = 1.0f;
}
vec2(T pA, T pB)
{
x = pA;
y = pB;
}
};
In regards to your Visual Studio debugger display: this is because of your scalarSwiz definition. You define an array of length 1 T value[1] and you put 2 scalarSwiz objects in a union. Because every member of a union share the same memory (or rather start at the same memory location), both of your value members point to the beginning of the data array. The watch window only displays the members and their values of a certain type, it has no knowledge of your quirky indexing. And because both arrays occupie the same memory, the same value is shown.
I updated my code regarding Timo's answer:
#include <iostream>
template<typename T>
void print(T value)
{
std::cout << "print func: " << value << std::endl;
}
template<typename T>
struct vec2
{
union
{
T data[2];
struct
{
T x, y;
};
};
vec2()
{
x = 0.0f;
y = 1.0f;
}
vec2(T pA, T pB)
{
x = pA;
y = pB;
}
};
int main(int argc, char *args[])
{
vec2<float> vec1{5.0f, 1.0f};
std::cout << "value vec1.data[0]: " << vec1.data[0] << std::endl;
std::cout << "value vec1.data[1]: " << vec1.data[1] << std::endl;
std::cout << "value vec1.x: " << vec1.x << std::endl;
std::cout << "value vec1.y: " << vec1.y << std::endl << std::endl;
print(vec1.data[0]);
print(vec1.data[1]);
print(vec1.x);
print(vec1.y);
std::cin.get();
}
I was playing with some reference to template base member code. Out of curiosity, I wondered if the compiler optimised out my references behind the scenes somehow (as the references were all to the same variables in the parent class every time). I decided a simple sizeof() test would tell me. To my great surprise, simply referencing the 3 float members of the class I was inheriting from, blew my class memory footprint up by 333%. This surprised and confused me greatly.
After some fiddling, I don't even know what is going on (but I suspect I'm being dumb).
Code: (compiled in Code::Blocks 13.12 using GCC 4.8.2 on Ubuntu 14.04)
#include <iostream>
template <typename T, unsigned int N>
class FooArray{
public:
FooArray(){
for (size_t i = 0; i < N; ++i)
{
m_data[i] = static_cast<T>(0);
}
}
FooArray(const T& _krv){
for (size_t i = 0; i < N; ++i)
{
m_data[i] = _krv;
}
}
T& operator[](unsigned int _index);
private:
T m_data[N];
};
template <typename T, unsigned int N>
T&
FooArray<T, N>::operator[](unsigned int _index)
{
return m_data[_index];
}
class Inherit0Ref : public FooArray<float, 3>{};
class Inherit1Ref : public FooArray<float, 3>
{
public:
Inherit1Ref():a((*this)[0]){}
float& a;
};
class Inherit2Ref : public FooArray<float, 3>
{
public:
Inherit2Ref():a((*this)[0]), b((*this)[1]){}
float& a;
float& b;
};
class Inherit3Ref : public FooArray<float, 3>
{
public:
Inherit3Ref():a((*this)[0]), b((*this)[1]), c((*this)[2]){}
float& a;
float& b;
float& c;
};
class Inherit2RefMul : public FooArray<float, 3>
{
public:
Inherit2RefMul():a((*this)[0]), b((*this)[1]){}
float& a, b;
};
class Inherit3RefMul : public FooArray<float, 3>
{
public:
Inherit3RefMul():a((*this)[0]), b((*this)[1]), c((*this)[2]){}
float& a, b, c;
};
class FloatRef
{
public:
FloatRef(float& _r):a(_r){}
float& a;
};
class WrapFloat
{
float pad;
};
class PadFloatRef
{
public:
PadFloatRef():a(pad), pad(0.0f){}
float& a;
float pad;
};
int main()
{
Inherit3Ref test;
test.a = 1.0f;
test.b = 2.0f;
test.c = 3.14f;
std::cout << test[0] << ", " << test[1] << ", " << test[2] << std::endl;
std::cout << "float size: " << sizeof(float) << std::endl;
std::cout << "float& size: " << sizeof(float&) << std::endl;
std::cout << "FloatRef size: " << sizeof(FloatRef) << std::endl;
std::cout << "WrapFloat size: " << sizeof(WrapFloat) << std::endl;
std::cout << "PadFloatRef size: " << sizeof(PadFloatRef) << std::endl;
std::cout << "FooArray<float, 3> size: " << sizeof(FooArray<float, 3>) << std::endl;
std::cout << "Inherit0Ref size: " << sizeof(Inherit0Ref) << std::endl;
std::cout << "Inherit1Ref size: " << sizeof(Inherit1Ref) << std::endl;
std::cout << "Inherit2Ref size: " << sizeof(Inherit2Ref) << std::endl;
std::cout << "Inherit3Ref size: " << sizeof(Inherit3Ref) << std::endl;
std::cout << "Inherit2RefMul size: " << sizeof(Inherit2RefMul) << std::endl;
std::cout << "Inherit3RefMul size: " << sizeof(Inherit3RefMul) << std::endl;
// Supposedly size 32, lets test assignment and access.
Inherit3RefMul testvar;
testvar.a = 5.0f;
testvar.b = 4.0f;
testvar.c = 3.142f;
// Interesting...
// testvar: 5, 0, 0
std::cout << "testvar: " << testvar[0] << ", " << testvar[1] << ", " << testvar[2] << std::endl;
return 0;
}
Output:
1, 2, 3.14
float size: 4
float& size: 4
FloatRef size: 8
WrapFloat size: 4
PadFloatRef size: 16
FooArray<float, 3> size: 12
Inherit0Ref size: 12
Inherit1Ref size: 24
Inherit2Ref size: 32
Inherit3Ref size: 40
Inherit2RefMul size: 32
Inherit3RefMul size: 32
testvar: 5, 0, 0
Very curious. :)
Why is a wrapped float reference(FloatRef) twice the size of a wrapped float(WrapFloat)?
Why does declaring 3 float references using one float reference keyword (Inherit3RefMul) yield the same footprint as the same class with 2 references rather than 3(Inherit2Ref)?
Why has only TestVar's first variable been populated while all 3 of test's are populated as expected?
Is there some way to achieve the functionality of Inherit3Ref without the ridiculous memory footprint of 40?
EDIT:
Please note:
sizeof(float&) == 4
Update:
Running alignof(float&) returns 4. I don't see the reason for a float[3] float&[3] class to have size 40 when all variables have size of 4 and align of 4.
The compiler must add padding to ensure that any member variables are appropriately aligned. float has size 4 and alignment 4, while references and pointers (to whatever) have typically size 8 (on 64bit machines) and alignment 8. Hence:
struct foo {
float m_data[3]; // size 3*4=12 begin=0 end=12
float&a; // size 8 begin=16 end=24 NOTE: 4 unused bytes
};
(Also note that
float&a,b;
is equivalent to
float&a;
float b;
but not to
typedef float&float_ref;
float_ref a,b;
this notation is hence best avoided for clarity)
A float is 4-bytes, a reference is 8-bytes. So an array of 3 floats will be 12-bytes. The only non-trivial bit is your Inherit3Ref, which will look like:
float[3];
*** padding to 8 byte boundary ***
float &[3];
Hence 12 bytes for the floats + 4 bytes additional padding + 24 bytes for the references to make 40. If you want to avoid the padding, you can make the class packed - which should get you down to 36 bytes.
Not sure why you call it "ridiculous" - it certainly has to be at least 36...
I was debugging some code involving pointers to member fields, and i decided to print them out to see their values. I had a function returning a pointer to member:
#include <stdio.h>
struct test {int x, y, z;};
typedef int test::*ptr_to_member;
ptr_to_member select(int what)
{
switch (what) {
case 0: return &test::x;
case 1: return &test::y;
case 2: return &test::z;
default: return NULL;
}
}
I tried using cout:
#include <iostream>
int main()
{
std::cout << select(0) << " and " << select(3) << '\n';
}
I got 1 and 0. I thought the numbers indicated the position of the field inside the struct (that is, 1 is y and 0 is x), but no, the printed value is actually 1 for non-null pointer and 0 for null pointer. I guess this is a standard-compliant behavior (even though it's not helpful) - am i right? In addition, is it possible for a compliant c++ implementation to print always 0 for pointers-to-members? Or even an empty string?
And, finally, how can i print a pointer-to-member in a meaningful manner? I came up with two ugly ways:
printf("%d and %d\n", select(0), select(3)); // not 64-bit-compatible, i guess?
ptr_to_member temp1 = select(0); // have to declare temporary variables
ptr_to_member temp2 = select(3);
std::cout << *(int*)&temp1 << " and " << *(int*)&temp2 << '\n'; // UGLY!
Any better ways?
Pointers to members are not as simple as you may think. Their size changes from compiler to compiler and from class to class depending on whether the class has virtual methods or not and whether it has multiple inheritance or not. Assuming they are int sized is not the right way to go. What you can do is print them in hexadecimal:
void dumpByte(char i_byte)
{
std::cout << std::hex << static_cast<int>((i_byte & 0xf0) >> 4);
std::cout << std::hex << static_cast<int>(i_byte & 0x0f));
} // ()
template <typename T>
void dumpStuff(T* i_pStuff)
{
const char* pStuff = reinterpret_cast<const char*>(i_pStuff);
size_t size = sizeof(T);
while (size)
{
dumpByte(*pStuff);
++pStuff;
--size;
} // while
} // ()
However, I'm not sure how useful that information will be to you since you don't know what is the structure of the pointers and what each byte (or several bytes) mean.
Member pointers aren't ordinary pointers. The overloads you expect for << aren't in fact there.
If you don't mind some type punning, you can hack something up to print the actual values:
int main()
{
ptr_to_member a = select(0), b = select(1);
std::cout << *reinterpret_cast<uint32_t*>(&a) << " and "
<< *reinterpret_cast<uint32_t*>(&b) << " and "
<< sizeof(ptr_to_member) << '\n';
}
You can display the raw values of these pointer-to-members as follows:
#include <iostream>
struct test {int x, y, z;};
typedef int test::*ptr_to_member;
ptr_to_member select(int what)
{
switch (what) {
case 0: return &test::x;
case 1: return &test::y;
case 2: return &test::z;
default: return NULL;
}
}
int main()
{
ptr_to_member x = select(0) ;
ptr_to_member y = select(1) ;
ptr_to_member z = select(2) ;
std::cout << *(void**)&x << ", " << *(void**)&y << ", " << *(void**)&z << std::endl ;
}
You get warnings about breaking strict anti-aliasing rules (see this link), but the result is what you might expect:
0, 0x4, 0x8
Nevertheless, the compiler is free to implement pointer-to-member functionality however it likes, so you can't rely on these values being meaningful.
I think you should use printf to solve this problen
#include <stdio.h>
struct test{int x,y,z;}
int main(int argc, char* argv[])
{
printf("&test::x=%p\n", &test::x);
printf("&test::y=%p\n", &test::y);
printf("&test::z=%p\n", &test::z);
return 0;
}
I want to work with unsigned 8-bit variables in C++. Either unsigned char or uint8_t do the trick as far as the arithmetic is concerned (which is expected, since AFAIK uint8_t is just an alias for unsigned char, or so the debugger presents it.
The problem is that if I print out the variables using ostream in C++ it treats it as char. If I have:
unsigned char a = 0;
unsigned char b = 0xff;
cout << "a is " << hex << a <<"; b is " << hex << b << endl;
then the output is:
a is ^#; b is 377
instead of
a is 0; b is ff
I tried using uint8_t, but as I mentioned before, that's typedef'ed to unsigned char, so it does the same. How can I print my variables correctly?
Edit: I do this in many places throughout my code. Is there any way I can do this without casting to int each time I want to print?
Use:
cout << "a is " << hex << (int) a <<"; b is " << hex << (int) b << endl;
And if you want padding with leading zeros then:
#include <iomanip>
...
cout << "a is " << setw(2) << setfill('0') << hex << (int) a ;
As we are using C-style casts, why not go the whole hog with terminal C++ badness and use a macro!
#define HEX( x )
setw(2) << setfill('0') << hex << (int)( x )
you can then say
cout << "a is " << HEX( a );
Edit: Having said that, MartinStettner's solution is much nicer!
I would suggest using the following technique:
struct HexCharStruct
{
unsigned char c;
HexCharStruct(unsigned char _c) : c(_c) { }
};
inline std::ostream& operator<<(std::ostream& o, const HexCharStruct& hs)
{
return (o << std::hex << (int)hs.c);
}
inline HexCharStruct hex(unsigned char _c)
{
return HexCharStruct(_c);
}
int main()
{
char a = 131;
std::cout << hex(a) << std::endl;
}
It's short to write, has the same efficiency as the original solution and it lets you choose to use the "original" character output. And it's type-safe (not using "evil" macros :-))
You can read more about this at http://cpp.indi.frih.net/blog/2014/09/tippet-printing-numeric-values-for-chars-and-uint8_t/ and http://cpp.indi.frih.net/blog/2014/08/code-critique-stack-overflow-posters-cant-print-the-numeric-value-of-a-char/. I am only posting this because it has become clear that the author of the above articles does not intend to.
The simplest and most correct technique to do print a char as hex is
unsigned char a = 0;
unsigned char b = 0xff;
auto flags = cout.flags(); //I only include resetting the ioflags because so
//many answers on this page call functions where
//flags are changed and leave no way to
//return them to the state they were in before
//the function call
cout << "a is " << hex << +a <<"; b is " << +b << endl;
cout.flags(flags);
The readers digest version of how this works is that the unary + operator forces a no op type conversion to an int with the correct signedness. So, an unsigned char converts to unsigned int, a signed char converts to int, and a char converts to either unsigned int or int depending on whether char is signed or unsigned on your platform (it comes as a shock to many that char is special and not specified as either signed or unsigned).
The only negative of this technique is that it may not be obvious what is happening to a someone that is unfamiliar with it. However, I think that it is better to use the technique that is correct and teach others about it rather than doing something that is incorrect but more immediately clear.
Well, this works for me:
std::cout << std::hex << (0xFF & a) << std::endl;
If you just cast (int) as suggested it might add 1s to the left of a if its most significant bit is 1. So making this binary AND operation guarantees the output will have the left bits filled by 0s and also converts it to unsigned int forcing cout to print it as hex.
I hope this helps.
In C++20 you'll be able to use std::format to do this:
std::cout << std::format("a is {:x}; b is {:x}\n", a, b);
Output:
a is 0; b is ff
In the meantime you can use the {fmt} library, std::format is based on. {fmt} also provides the print function that makes this even easier and more efficient (godbolt):
fmt::print("a is {:x}; b is {:x}\n", a, b);
Disclaimer: I'm the author of {fmt} and C++20 std::format.
Hm, it seems I re-invented the wheel yesterday... But hey, at least it's a generic wheel this time :) chars are printed with two hex digits, shorts with 4 hex digits and so on.
template<typename T>
struct hex_t
{
T x;
};
template<typename T>
hex_t<T> hex(T x)
{
hex_t<T> h = {x};
return h;
}
template<typename T>
std::ostream& operator<<(std::ostream& os, hex_t<T> h)
{
char buffer[2 * sizeof(T)];
for (auto i = sizeof buffer; i--; )
{
buffer[i] = "0123456789ABCDEF"[h.x & 15];
h.x >>= 4;
}
os.write(buffer, sizeof buffer);
return os;
}
I think TrungTN and anon's answer is okay, but MartinStettner's way of implementing the hex() function is not really simple, and too dark, considering hex << (int)mychar is already a workaround.
here is my solution to make "<<" operator easier:
#include <sstream>
#include <iomanip>
string uchar2hex(unsigned char inchar)
{
ostringstream oss (ostringstream::out);
oss << setw(2) << setfill('0') << hex << (int)(inchar);
return oss.str();
}
int main()
{
unsigned char a = 131;
std::cout << uchar2hex(a) << std::endl;
}
It's just not worthy implementing a stream operator :-)
I think we are missing an explanation of how these type conversions work.
char is platform dependent signed or unsigned. In x86 char is equivalent to signed char.
When an integral type (char, short, int, long) is converted to a larger capacity type, the conversion is made by adding zeros to the left in case of unsigned types and by sign extension for signed ones. Sign extension consists in replicating the most significant (leftmost) bit of the original number to the left till we reach the bit size of the target type.
Hence if I am in a signed char by default system and I do this:
char a = 0xF0; // Equivalent to the binary: 11110000
std::cout << std::hex << static_cast<int>(a);
We would obtain F...F0 since the leading 1 bit has been extended.
If we want to make sure that we only print F0 in any system we would have to make an additional intermediate type cast to an unsigned char so that zeros are added instead and, since they are not significant for a integer with only 8-bits, not printed:
char a = 0xF0; // Equivalent to the binary: 11110000
std::cout << std::hex << static_cast<int>(static_cast<unsigned char>(a));
This produces F0
I'd do it like MartinStettner but add an extra parameter for number of digits:
inline HexStruct hex(long n, int w=2)
{
return HexStruct(n, w);
}
// Rest of implementation is left as an exercise for the reader
So you have two digits by default but can set four, eight, or whatever if you want to.
eg.
int main()
{
short a = 3142;
std:cout << hex(a,4) << std::endl;
}
It may seem like overkill but as Bjarne said: "libraries should be easy to use, not easy to write".
I would suggest:
std::cout << setbase(16) << 32;
Taken from:
http://www.cprogramming.com/tutorial/iomanip.html
You can try the following code:
unsigned char a = 0;
unsigned char b = 0xff;
cout << hex << "a is " << int(a) << "; b is " << int(b) << endl;
cout << hex
<< "a is " << setfill('0') << setw(2) << int(a)
<< "; b is " << setfill('0') << setw(2) << int(b)
<< endl;
cout << hex << uppercase
<< "a is " << setfill('0') << setw(2) << int(a)
<< "; b is " << setfill('0') << setw(2) << int(b)
<< endl;
Output:
a is 0; b is ff
a is 00; b is ff
a is 00; b is FF
I use the following on win32/linux(32/64 bit):
#include <iostream>
#include <iomanip>
template <typename T>
std::string HexToString(T uval)
{
std::stringstream ss;
ss << "0x" << std::setw(sizeof(uval) * 2) << std::setfill('0') << std::hex << +uval;
return ss.str();
}
I realize this is an old question, but its also a top Google result in searching for a solution to a very similar problem I have, which is the desire to implement arbitrary integer to hex string conversions within a template class. My end goal was actually a Gtk::Entry subclass template that would allow editing various integer widths in hex, but that's beside the point.
This combines the unary operator+ trick with std::make_unsigned from <type_traits> to prevent the problem of sign-extending negative int8_t or signed char values that occurs in this answer
Anyway, I believe this is more succinct than any other generic solution. It should work for any signed or unsigned integer types, and throws a compile-time error if you attempt to instantiate the function with any non-integer types.
template <
typename T,
typename = typename std::enable_if<std::is_integral<T>::value, T>::type
>
std::string toHexString(const T v)
{
std::ostringstream oss;
oss << std::hex << +((typename std::make_unsigned<T>::type)v);
return oss.str();
}
Some example usage:
int main(int argc, char**argv)
{
int16_t val;
// Prints 'ff' instead of "ffffffff". Unlike the other answer using the '+'
// operator to extend sizeof(char) int types to int/unsigned int
std::cout << toHexString(int8_t(-1)) << std::endl;
// Works with any integer type
std::cout << toHexString(int16_t(0xCAFE)) << std::endl;
// You can use setw and setfill with strings too -OR-
// the toHexString could easily have parameters added to do that.
std::cout << std::setw(8) << std::setfill('0') <<
toHexString(int(100)) << std::endl;
return 0;
}
Update: Alternatively, if you don't like the idea of the ostringstream being used, you can combine the templating and unary operator trick with the accepted answer's struct-based solution for the following. Note that here, I modified the template by removing the check for integer types. The make_unsigned usage might be enough for compile time type safety guarantees.
template <typename T>
struct HexValue
{
T value;
HexValue(T _v) : value(_v) { }
};
template <typename T>
inline std::ostream& operator<<(std::ostream& o, const HexValue<T>& hs)
{
return o << std::hex << +((typename std::make_unsigned<T>::type) hs.value);
}
template <typename T>
const HexValue<T> toHex(const T val)
{
return HexValue<T>(val);
}
// Usage:
std::cout << toHex(int8_t(-1)) << std::endl;
If you're using prefill and signed chars, be careful not to append unwanted 'F's
char out_character = 0xBE;
cout << setfill('0') << setw(2) << hex << unsigned short(out_character);
prints: ffbe
using int instead of short results in ffffffbe
To prevent the unwanted f's you can easily mask them out.
char out_character = 0xBE;
cout << setfill('0') << setw(2) << hex << unsigned short(out_character) & 0xFF;
I'd like to post my re-re-inventing version based on #FredOverflow's. I made the following modifications.
fix:
Rhs of operator<< should be of const reference type. In #FredOverflow's code, h.x >>= 4 changes output h, which is surprisingly not compatible with standard library, and type T is requared to be copy-constructable.
Assume only CHAR_BITS is a multiple of 4. #FredOverflow's code assumes char is 8-bits, which is not always true, in some implementations on DSPs, particularly, it is not uncommon that char is 16-bits, 24-bits, 32-bits, etc.
improve:
Support all other standard library manipulators available for integral types, e.g. std::uppercase. Because format output is used in _print_byte, standard library manipulators are still available.
Add hex_sep to print separate bytes (note that in C/C++ a 'byte' is by definition a storage unit with the size of char). Add a template parameter Sep and instantiate _Hex<T, false> and _Hex<T, true> in hex and hex_sep respectively.
Avoid binary code bloat. Function _print_byte is extracted out of operator<<, with a function parameter size, to avoid instantiation for different Size.
More on binary code bloat:
As mentioned in improvement 3, no matter how extensively hex and hex_sep is used, only two copies of (nearly) duplicated function will exits in binary code: _print_byte<true> and _print_byte<false>. And you might realized that this duplication can also be eliminated using exactly the same approach: add a function parameter sep. Yes, but if doing so, a runtime if(sep) is needed. I want a common library utility which may be used extensively in the program, thus I compromised on the duplication rather than runtime overhead. I achieved this by using compile-time if: C++11 std::conditional, the overhead of function call can hopefully be optimized away by inline.
hex_print.h:
namespace Hex
{
typedef unsigned char Byte;
template <typename T, bool Sep> struct _Hex
{
_Hex(const T& t) : val(t)
{}
const T& val;
};
template <typename T, bool Sep>
std::ostream& operator<<(std::ostream& os, const _Hex<T, Sep>& h);
}
template <typename T> Hex::_Hex<T, false> hex(const T& x)
{ return Hex::_Hex<T, false>(x); }
template <typename T> Hex::_Hex<T, true> hex_sep(const T& x)
{ return Hex::_Hex<T, true>(x); }
#include "misc.tcc"
hex_print.tcc:
namespace Hex
{
struct Put_space {
static inline void run(std::ostream& os) { os << ' '; }
};
struct No_op {
static inline void run(std::ostream& os) {}
};
#if (CHAR_BIT & 3) // can use C++11 static_assert, but no real advantage here
#error "hex print utility need CHAR_BIT to be a multiple of 4"
#endif
static const size_t width = CHAR_BIT >> 2;
template <bool Sep>
std::ostream& _print_byte(std::ostream& os, const void* ptr, const size_t size)
{
using namespace std;
auto pbyte = reinterpret_cast<const Byte*>(ptr);
os << hex << setfill('0');
for (int i = size; --i >= 0; )
{
os << setw(width) << static_cast<short>(pbyte[i]);
conditional<Sep, Put_space, No_op>::type::run(os);
}
return os << setfill(' ') << dec;
}
template <typename T, bool Sep>
inline std::ostream& operator<<(std::ostream& os, const _Hex<T, Sep>& h)
{
return _print_byte<Sep>(os, &h.val, sizeof(T));
}
}
test:
struct { int x; } output = {0xdeadbeef};
cout << hex_sep(output) << std::uppercase << hex(output) << endl;
output:
de ad be ef DEADBEEF
This will also work:
std::ostream& operator<< (std::ostream& o, unsigned char c)
{
return o<<(int)c;
}
int main()
{
unsigned char a = 06;
unsigned char b = 0xff;
std::cout << "a is " << std::hex << a <<"; b is " << std::hex << b << std::endl;
return 0;
}
I have used in this way.
char strInput[] = "yourchardata";
char chHex[2] = "";
int nLength = strlen(strInput);
char* chResut = new char[(nLength*2) + 1];
memset(chResut, 0, (nLength*2) + 1);
for (int i = 0; i < nLength; i++)
{
sprintf(chHex, "%02X", strInput[i]& 0x00FF);
memcpy(&(chResut[i*2]), chHex, 2);
}
printf("\n%s",chResut);
delete chResut;
chResut = NULL;