I want to overload an operator (e.g. operator<<) with different types, but also change only 1 or 2 values in the function itself.
I want to get some fancy output of a vector with the primitive integer types. I have tried to create a template function like template<int width, typename T> operator<<...
but this would need to set the width and typename explicitly with each call of the operator<<
e.g.
I have a following minimal code example (which is not the shortest tbh):
main.cpp
#include <iostream>
#include <vector>
#include "utils.h"
using namespace std;
int main(int argc, char* argv[]) {
vector<int8_t> vec_s_1 = {1, 2, 3, -1, -2, -123};
vector<uint8_t> vec_u_1 = {1, 2, 3, 127, 128, 129};
vector<int16_t> vec_s_2 = {1, 2, 3, -1, -2, -123};
vector<uint16_t> vec_u_2 = {1, 2, 3, 127, 128, 129};
vector<int32_t> vec_s_3 = {1, 2, 3, -1, -2, -123};
vector<uint32_t> vec_u_3 = {1, 2, 3, 127, 128, 129};
vector<int64_t> vec_s_4 = {1, 2, 3, -1, -2, -123};
vector<uint64_t> vec_u_4 = {1, 2, 3, 127, 128, 129};
cout << "vec_s_1: " << vec_s_1 << endl;
cout << "vec_u_1: " << vec_u_1 << endl;
cout << endl;
cout << "vec_s_2: " << vec_s_2 << endl;
cout << "vec_u_2: " << vec_u_2 << endl;
cout << endl;
cout << "vec_u_3: " << vec_u_3 << endl;
cout << "vec_s_3: " << vec_s_3 << endl;
cout << endl;
cout << "vec_s_4: " << vec_s_4 << endl;
cout << "vec_u_4: " << vec_u_4 << endl;
return 0;
}
utils.h
#ifndef MODULO_SEQUENCE_UTILS_H
#define MODULO_SEQUENCE_UTILS_H
#include <vector>
#include <iomanip>
#include <ostream>
#include <sstream>
using namespace std;
template<typename T>
ostream& operator<<(ostream& os, const vector<T>& obj);
#endif // MODULO_SEQUENCE_UTILS_H
utils.cpp
#include "utils.h"
#define GET_FUNCTION(WIDTH, TYPENAME, MASK) \
template<> ostream& operator<<(ostream& os, const vector<TYPENAME>& obj) { \
size_t size = obj.size(); \
os << "["; \
for (size_t i = 0; i < size; ++i) { \
if (i > 0) { \
os << ", "; \
} \
stringstream ss; \
ss << "0x" << hex << uppercase << setw(WIDTH) << setfill('0') << (obj[i] & MASK); \
os << ss.str(); \
} \
os << "]"; \
return os; \
}
GET_FUNCTION(2, int8_t, 0xFF)
GET_FUNCTION(2, uint8_t, 0xFF)
GET_FUNCTION(4, int16_t, 0xFFFF)
GET_FUNCTION(4, uint16_t, 0xFFFF)
GET_FUNCTION(8, int32_t, 0xFFFFFFFF)
GET_FUNCTION(8, uint32_t, 0xFFFFFFFF)
GET_FUNCTION(16, int64_t, 0xFFFFFFFFFFFFFFFF)
GET_FUNCTION(16, uint64_t, 0xFFFFFFFFFFFFFFFF)
So far it is working like expected and the output is like I wanted to have it. It is solved by calling #define
for each function separately (which is a really looking ugly code).
The output looks like this:
vec_s_1: [0x01, 0x02, 0x03, 0xFF, 0xFE, 0x85]
vec_u_1: [0x01, 0x02, 0x03, 0x7F, 0x80, 0x81]
vec_s_2: [0x0001, 0x0002, 0x0003, 0xFFFF, 0xFFFE, 0xFF85]
vec_u_2: [0x0001, 0x0002, 0x0003, 0x007F, 0x0080, 0x0081]
vec_u_3: [0x00000001, 0x00000002, 0x00000003, 0x0000007F, 0x00000080, 0x00000081]
vec_s_3: [0x00000001, 0x00000002, 0x00000003, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFF85]
vec_s_4: [0x0000000000000001, 0x0000000000000002, 0x0000000000000003, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFE, 0xFFFFFFFFFFFFFF85]
vec_u_4: [0x0000000000000001, 0x0000000000000002, 0x0000000000000003, 0x000000000000007F, 0x0000000000000080, 0x0000000000000081]
I need the different widths of the leading zeros in the output plus the mask for getting the exact hex number for each type.
My question is: How can/could I achieve the same result with only using templates?
Aucun commentaire:
Enregistrer un commentaire