Reading a WORD variable from a CArchive and casting to int at the same time - casting

This might sound basic but:
WORD wSong = 0;
CArchive ar;
...
ar >> wSong;
m_sPublicTalkInfo.iSongStart = static_cast<int>(wSong);
At the moment I read the WORD into a specific variable and the cast it.
Can I read it in and cast at the same time?
Please note I can't serialize a int. It must be a WORD and cast to int.
Or
ar >> wSong;
m_sPublicTalkInfo.iSongStart = static_cast<int>(wSong);

I don't think there is a direct way. You could implement a helper function:
template <typename T, typename U>
T readAndCast (CArchive& ar) {
U x;
ar >> x;
return static_cast<T> (x);
}
m_sPublicTalkInfo.iSongStart = readAndCast<int, WORD>(ar);
It might be better to use the fixed-width integer types in your program, i.e. perhaps int_least16_t instead of int to be sure the type has the right size. WORD is fixed to 16bit, but int isn't. Also, WORD is unsigned and int isn't, so there could be an overflow during casting.

This is a example of how you could create a wrapper if you want the serialize syntax to remain consistent. It's designed to work with integrals and MFC unsigned types only.
#include <iostream>
#include <cstdint>
#include <sstream>
#include <type_traits>
// Fake the MFC types
using BYTE = std::uint8_t;
using WORD = std::uint16_t;
using DWORD = std::uint32_t;
using QWORD = std::uint64_t;
template<typename T>
struct is_valid_save_type : std::bool_constant<
std::is_same_v<BYTE, T> ||
std::is_same_v<WORD, T> ||
std::is_same_v<DWORD, T> ||
std::is_same_v<QWORD, T>
> {};
template<typename T>
struct is_valid_load_type : is_valid_save_type<T> {};
// Saves type T as a SaveType
template<typename T, typename SaveType>
struct save_as_type
{
explicit save_as_type(T value) : value(value) {}
explicit operator SaveType() const
{
return static_cast<SaveType>(value);
}
private:
T value;
// This class only works with integrals
static_assert(std::is_integral_v<T>);
// SaveType should be BYTE/WORD/DWORD/QWORD only
static_assert(is_valid_save_type<SaveType>::value);
};
// Loads type T as a LoadType
template<typename T, typename LoadType>
struct load_as_type
{
explicit load_as_type(T& value) : value_(value) {}
load_as_type& operator=(LoadType rhs)
{
value_ = rhs;
return *this;
}
private:
T& value_;
// T should be an integral
static_assert(std::is_integral_v<T>);
// T must be non-constant
static_assert(!std::is_const_v<T>);
// LoadType should be BYTE/WORD/DWORD/QWORD only
static_assert(is_valid_load_type<LoadType>::value);
};
class CArchive;
// Make the above types serializable
template<typename T, typename SaveType>
CArchive& operator<<(CArchive& ar, save_as_type<T, SaveType> const& s)
{
ar << static_cast<SaveType>(s);
}
template<typename T, typename LoadType>
CArchive& operator>>(CArchive& ar, load_as_type<T, LoadType> l)
{
LoadType t{};
ar >> t;
l = t;
}
// Use the following two functions in your code
template<typename SaveType, typename T>
save_as_type<T, SaveType> save_as(T const& t)
{
return save_as_type<T, SaveType>{ t };
}
template<typename LoadType, typename T>
load_as_type<T, LoadType> load_as(T& t)
{
return load_as_type<T, LoadType>{ t };
}
// Prevent loading into temporaries; i.e. load_as<BYTE>(11);
template<typename T, typename LoadType>
load_as_type<T, LoadType> load_as(const T&& t) = delete;
// Fake MFC Archive
class CArchive
{
public:
CArchive& operator<<(int i)
{
std::cout << "Saving " << i << " as an int\n";
return *this;
}
CArchive& operator<<(BYTE b)
{
std::cout << "Saving " << (int)b << " as a BYTE\n";
return *this;
}
CArchive& operator<<(WORD w)
{
std::cout << "Saving " << (int)w << " as a WORD\n";
return *this;
}
CArchive& operator<<(DWORD d)
{
std::cout << "Saving " << (int)d << " as a DWORD\n";
return *this;
}
CArchive& operator>>(int& i)
{
std::cout << "Loading as an int\n";
return *this;
}
CArchive& operator>>(BYTE& b)
{
std::cout << "Loading as a BYTE\n";
return *this;
}
CArchive& operator>>(WORD& w)
{
std::cout << "Loading as a WORD\n";
return *this;
}
CArchive& operator>>(DWORD& d)
{
std::cout << "Loading as a DWORD\n";
return *this;
}
};
int main()
{
CArchive ar;
int out_1 = 1;
int out_2 = 2;
int out_3 = 3;
int out_4 = 4;
ar << out_1 <<
save_as<BYTE>(out_2) <<
save_as<WORD>(out_3) <<
save_as<DWORD>(out_4);
std::cout << "\n";
int in_1 = 0;
int in_2 = 0;
int in_3 = 0;
int in_4 = 0;
ar >> in_1 >>
load_as<BYTE>(in_2) >>
load_as<WORD>(in_3) >>
load_as<DWORD>(in_4);
return 0;
}
Output:
Saving 1 as an int
Saving 2 as a BYTE
Saving 3 as a WORD
Saving 4 as a DWORD
Loading as an int
Loading as a BYTE
Loading as a WORD
Loading as a DWORD

Related

Non-type template argument, from constant function argument?

I'm experimenting with C++ templates, and a kind of heterogenous type-safe map. Keys go with specific types. An example use would be something like a CSS stylesheet. I've got it to where I can things write:
styles.set<StyleKey::fontFamily>("Helvetica");
styles.set<StyleKey::fontSize>(23.0);
That type checks as desired; it won't compile calls where the key does not match it's intended value type.
But I'm wondering if there's also a way to write it like this:
styles.set(StyleKey::fontFamily, "Helvetica");
styles.set(StyleKey::fontSize, 23.0);
... and have it deduce the same thing, because the first argument is a constant.
Here's my flailing attempt, pasted below and on godbolt. The set2 template does not work.
#include <iostream>
#include <string>
using namespace std;
struct color {
float r,g,b;
};
ostream &operator <<(ostream &out, const color &c) {
return out << "[" << c.r << ',' << c.g << ',' << c.b << "]";
}
// Gives something that would have types: string, float, color, bool
enum class StyleKey {
fontFamily = 1, fontSize, fontColor, visible
};
template <StyleKey key>
struct KeyValueType {
};
struct StyleMap;
template <>
struct KeyValueType<StyleKey::fontFamily> {
typedef string value_type;
static void set(StyleMap *sm, value_type value);
};
template <>
struct KeyValueType<StyleKey::fontSize> {
typedef float value_type;
static void set(StyleMap *sm, value_type value);
};
struct StyleMap {
string fontFamily = "";
float fontSize = 14;
color fontColor = color{0,0,0};
bool visible = true;
template <StyleKey key>
void set(typename KeyValueType<key>::value_type value) {
cout << "set " << (int)key << " value: " << value << endl;
KeyValueType<key>::set(this, value);
}
template <StyleKey key>
void set2(StyleKey key2, typename KeyValueType<key>::value_type value) {
static_assert(key == key2);
cout << "set " << (int)key << " value: " << value << endl;
}
};
void KeyValueType<StyleKey::fontFamily>::set(StyleMap *sm, string str) {
sm->fontFamily = str;
}
void KeyValueType<StyleKey::fontSize>::set(StyleMap *sm, float sz) {
sm->fontSize = sz;
}
void print(const StyleMap &sm) {
cout << "font family : " << sm.fontFamily << endl;
cout << "font size : " << sm.fontSize << endl;
cout << "color : " << sm.fontColor << endl;
cout << "visible : " << sm.visible << endl;
}
int main() {
// Goal:
//
// StyleMap styles;
// styles[fontFamily] = "Helvetica";
// styles[fontSize] = 15.0;
// string fam = styles[fontFamily]
// float sz = styles[fontSize];
StyleMap styles;
// This works!
styles.set<StyleKey::fontFamily>("Helvetica");
styles.set<StyleKey::fontSize>(23.0);
// This won't compile, as desired
// styles.set<StyleKey::fontFamily>(20);
// But can we write it like this?
// styles.set2(StyleKey::fontFamily, "Helvetica");
// styles.set2(StyleKey::fontSize, 23.0);
print(styles);
}
You can't do SFINAE or specialization on function parameters, only template parameters. That means this can't work using your current approach.
What you could do is change your StyleKeys from being enum values to being empty tag structs with different types. Then you could specialize KeyValueType on each of those types and pass an object of one of those types to StyleMap::set. It can then use the type of that object to deduce the correct KeyValueType specialization to dispatch to.
namespace StyleKey {
static constexpr inline struct FontFamily {} fontFamily;
static constexpr inline struct FontSize {} fontSize;
};
template <typename KeyType>
struct KeyValueType {};
struct StyleMap;
template <>
struct KeyValueType<StyleKey::FontFamily> {
using value_type = std::string;
static void set(StyleMap *sm, value_type value);
};
template <>
struct KeyValueType<StyleKey::FontSize> {
using value_type = float;
static void set(StyleMap *sm, value_type value);
};
struct StyleMap {
std::string fontFamily = "";
float fontSize = 14;
template <auto key>
void set(typename KeyValueType<std::remove_const_t<decltype(key)>>::value_type value) {
KeyValueType<std::remove_const_t<decltype(key)>>::set(this, value);
}
template <typename KeyType>
void set2(KeyType key, typename KeyValueType<KeyType>::value_type value) {
KeyValueType<KeyType>::set(this, value);
}
};
void KeyValueType<StyleKey::FontFamily>::set(StyleMap *sm, std::string str) {
sm->fontFamily = str;
}
void KeyValueType<StyleKey::FontSize>::set(StyleMap *sm, float sz) {
sm->fontSize = sz;
}
Demo
Note: This approach will also work for the goal mentioned in the comment in your main function. Example.

Function specialization to access struct members with getter using enum

I have an enum and a struct
enum STORE_ENUM { A_DATA, B_DATA, C_DATA, D_DATA };
struct Store {
int a;
char b;
long c;
bool d;
}
and I want to access its members with a specialized get function that basically looks like this
T get(STORE_ENUM,store s);
and it returns the appropriate type and hopefully statically type checks.
is this possible in C++?
Yes it's possible. The boost PFR library allows something very similar to how you've envisaged it, e.g.:
auto& x = boost::pfr::get<B_DATA>(s);
See the tutorial here.
With C++17, you can do the following
#include <iostream>
enum struct STORE_ENUM { A_DATA, B_DATA, C_DATA, D_DATA };
struct Store {
int a;
char b;
long c;
bool d;
};
template<STORE_ENUM storeEnum>
auto get(Store const & s){
if constexpr (storeEnum == STORE_ENUM::A_DATA) return s.a;
if constexpr (storeEnum == STORE_ENUM::B_DATA) return s.b;
if constexpr (storeEnum == STORE_ENUM::C_DATA) return s.c;
if constexpr (storeEnum == STORE_ENUM::D_DATA) return s.d;
}
int main(){
auto store = Store{ 0, 'a', 4l, true};
std::cout << get<STORE_ENUM::A_DATA>( store) << "\n";
std::cout << get<STORE_ENUM::B_DATA>( store) << "\n";
std::cout << get<STORE_ENUM::C_DATA>( store) << "\n";
std::cout << get<STORE_ENUM::D_DATA>( store) << "\n";
}
See https://godbolt.org/z/1vffh3
In my solution, we don't need enums. It uses templates.
#include <iostream>
#include <type_traits>
struct Store
{
int a;
char b;
long c;
bool d;
Store() //Default constructor
{
a = 0;
b = 0;
c = 0;
d = false;
}
Store(int a, char b, long c, bool d) //Constructor. Custom values.
{
this->a = a;
this->b = b;
this->c = c;
this->d = d;
}
template <typename T = int,
typename = typename std::enable_if<std::is_same<T, int>::value ||
std::is_same<T, char>::value ||
std::is_same<T, long>::value ||
std::is_same<T, bool>::value,
void>::type>
T GetData()
{
if (std::is_same<T, char>::value)
{
return b;
}
if (std::is_same<T, long>::value)
{
return c;
}
if (std::is_same<T, bool>::value)
{
return d;
}
return a;
}
};
int main()
{
Store store { 63, '#', 65, true };
std::cout << store.GetData() << std::endl;
std::cout << store.GetData<>() << std::endl;
std::cout << store.GetData<int>() << std::endl;
std::cout << store.GetData<char>() << std::endl;
std::cout << store.GetData<long>() << std::endl;
std::cout << std::boolalpha << store.GetData<bool>() << std::endl;
}
Output
63
63
63
#
65
true
Compile
clang++ ./main.cpp -std=c++11 or g++ ./main.cpp -std=c++11
Check/run this code in https://repl.it/#JomaCorpFX/FunctionSpecialization#main.cpp
std::tuple basically does this, and your type is basically a tuple. So the easy and fast way is to just reuse std::tuple's machinery.
In c++14 it might look like this:
template<STORE_ENUM e>
auto get( Store s ){
return std::get<(unsigned)e>(std::make_tuple(s.a,s.b,s.c,s.d));
}
template<STORE_ENUM e, class T>
void set( Store& s, T t ){
std::get<(unsigned)e>(std::tie(s.a,s.b,s.c,s.d))=t;
}
This is c++14, but the missing bit for c++11 is easy:
template<STORE_ENUM e>
using store_type = typename std::tuple_element<(unsigned)e, std::tuple<int,char,long,bool>>::type;
template<STORE_ENUM e>
store_type<e> get( Store s ) {
return std::get<(unsigned)e>(std::make_tuple(s.a,s.b,s.c,s.d));
}
template<STORE_ENUM e>
void set( Store& s, store_type<e> v ){
std::get<(unsigned)e>(std::tie(s.a,s.b,s.c,s.d))=v;
}

How to have inheritance between template with union?

I have the following two objects. Im wondering if there is a way to have Pixel as a base class of PixelBGR so that any operator (+,-,*,/, [], etc.) could be used without redefining them ?
template<class T, std::size_t N>
struct Pixel
{
T ch[N];
inline T& operator[](const int x)
{
return ch[x];
}
};
template<class T>
struct PixelBGR
{
union
{
struct
{
T b;
T g;
T r;
};
T ch[3];
};
inline T& operator[](const int x)
{
return ch[x];
}
};
EDIT: As suggested by πάντα ῥεῖ, here more details about what Im trying to do.
Im trying to have a generic class Pixel, which will be template to handle any type or size.
The usual are 1,2,3,4,8 or 16. The class with defines some operator such as +,-,*, etc.
Since most of the time, the Pixel<T,3> is a BGR pixel, I would like to define rapid access to r,g and b to avoid confusion, but still store it as BGR.
But the derived class should also provide the Operator which will be generic based on N.
EDIT2: By reading the comment of SergeyA, I forgot to say that the struct Pixel must not change size.
So I think balki answer is the best, by using member function. I was trying to make it with variables to avoid too much char ie: adding the (), but it seems to be too complicated for nothing. I still investigating CRTP, but I dont get it well, Im reading on that.
Answering the question as asked, this should give OP reuse of the operators without any undefined behavior:
#include <cstddef>
template<class T, std::size_t N>
struct Pixel
{
T ch[N];
inline T& operator[](const int x)
{
return ch[x];
}
Pixel& operator+= (const Pixel& ) { return *this;}
};
template<class T, std::size_t N>
Pixel<T, N> operator+ (const Pixel<T, N>& l, const Pixel<T, N>& r);
template<class T>
struct BgrPixel : Pixel<T, 3> {
using base = Pixel<T, 3>;
using base::base;
BgrPixel(const base& b) : base(b) { };
T& b = base::ch[0];
T& g = base::ch[1];
T& r = base::ch[2];
};
BgrPixel<int> a, b;
BgrPixel<int> c = a + b;
Alterinative would be to have b(), g() and r() as a member functions, but this would require you to access them as functions. You would also need const and non-const versions of them.
The benefits, however, would be that the size of the struct will not be increased and copy assignment would work naturally (which, in turn, could be solved by providing custom copy assignment).
The Curiously Recurring Template Pattern (CRTP) would work well in this case. In the CRTP the Derived class is used as a template argument to the Base class. Chapter 16.3 The Curiously Recurring Template Pattern (CRTP), from the C++ Templates - The Complete Guide, by David Vandevoorde and Nicolai M. Josuttis, explains things in more detail.
From the comments below, the usage of a union{struct{...}...} causes undefined behaviour (UB), but there have been some contradicting opinions upon this. As far as I'm aware, it is a gnu extension and supported by almost every compiler. glm for example uses union-structs quite very often.
As an alternative approach, you can use aliases (references) for the r,g,b variables.
#include <iostream>
template<typename T, std::size_t N, template<typename,std::size_t> class B >
struct Pixel
{
B<T,N> *crtp = static_cast<B<T,N>*>(this);
T& operator[](std::size_t x)
{
return crtp->ch[x];
}
Pixel& operator = (const Pixel &t)
{
crtp->ch[0] = t.crtp->ch[0];
crtp->ch[1] = t.crtp->ch[1];
crtp->ch[2] = t.crtp->ch[2];
return *crtp;
}
B<T,N> operator + (const B<T,N> &t)
{
B<T,N> tmp;
tmp[0] = crtp->ch[0] + t.crtp->ch[0];
tmp[1] = crtp->ch[1] + t.crtp->ch[1];
tmp[2] = crtp->ch[2] + t.crtp->ch[2];
return tmp;
}
B<T,N> operator - (const B<T,N> &t)
{
B<T,N> tmp;
tmp[0] = crtp->ch[0] - t.crtp->ch[0];
tmp[1] = crtp->ch[1] - t.crtp->ch[1];
tmp[2] = crtp->ch[2] - t.crtp->ch[2];
return tmp;
}
};
template<typename T, std::size_t N=3>
struct PixelBGR : Pixel<T, N, PixelBGR>
{
T ch[3];
T &r;
T &g;
T &b;
PixelBGR() : ch{},r(ch[0]),g(ch[1]),b(ch[2])
{}
PixelBGR& operator = (const PixelBGR &p)
{
ch[0] = p.ch[0];
ch[1] = p.ch[1];
ch[2] = p.ch[2];
return *this;
}
};
int main()
{
PixelBGR<int> p;
p.r = 25;
p.g = 14;
p.b = 58;
std::cout<< p[0] <<" , "<<p[1]<<" , "<<p[2] <<std::endl;
PixelBGR<int> q;
q = p;
std::cout<< q[0] <<" , "<<q[1]<<" , "<<q[2] <<std::endl;
PixelBGR<int> res1;
res1 = q + p;
std::cout<< res1.r <<" , "<<res1.g<<" , "<<res1.b <<std::endl;
PixelBGR<int> res2;
res2 = q - p;
std::cout<< res2.r <<" , "<<res2.g<<" , "<<res2.b <<std::endl;
}
Result:
25 , 14 , 58
25 , 14 , 58
50 , 28 , 116
0 , 0 , 0
Example using references: https://rextester.com/AZWG4319
Example using union-struct: https://rextester.com/EACC87146
First thanks to all of you for advise, and special thanks to #Constantinos Glynos, #balki and #SergeyA for the example they provide, those help me to achieve a solution that match my need.
I implemented the BGR and BGRA to show that the N works fine, now I just need to implement all the operator, and functions that I require.
Please feel free to edit, or tell me if there is something wrong with this.
Pixel.h
#include <cstdio> // std::size_t
#include <iostream> // std::cout
template<typename T, std::size_t N, template<typename, std::size_t> class B >
struct Pixel
{
T ch[N];
// ==============================================================
// Overload the accessor (so .ch[0] == direct access with [0].
T& operator[](std::size_t x){ return ch[x]; }
// ==============================================================
// Copy-assignement
Pixel& operator=( const Pixel &t )
{
for ( int i = 0; i < N; i++ )
ch[i] = t.ch[i];
return *this;
}
// ==============================================================
// Operator
B<T, N> operator+( const B<T, N> &t )
{
B<T, N> tmp;
for ( int i = 0; i < N; i++ )
tmp[i] = ch[i] + t.ch[i];
return tmp;
}
B<T, N> operator-( const B<T, N> &t )
{
B<T, N> tmp;
for ( int i = 0; i < N; i++ )
tmp[i] = ch[i] - t.ch[i];
return tmp;
}
template<typename T, std::size_t N, template<typename, std::size_t> class B >
friend std::ostream& operator<<( std::ostream& os, const Pixel &t );
};
// To print the vector
template<typename T, std::size_t N, template<typename, std::size_t> class B >
std::ostream& operator<<( std::ostream& os, const B<T, N> &t )
{
os << "Pixel: (" << t.ch[0];
for ( int i = 1; i < N; i++ )
os << ", " << t.ch[i];
os << ")";
return os;
}
template<typename T, std::size_t N = 3>
struct BGR : Pixel<T, N, BGR>
{
T& b() { return ch[0]; }
T& g() { return ch[1]; }
T& r() { return ch[2]; }
};
template<typename T, std::size_t N = 4>
struct BGRA : Pixel<T, N, BGRA>
{
T& b() { return ch[0]; }
T& g() { return ch[1]; }
T& r() { return ch[2]; }
T& a() { return ch[3]; }
};
Main.cpp
int main() {
std::cout << "Sizeof a float BGR: " << sizeof(BGR<float>) << std::endl;
std::cout << "Sizeof a float BGRA: " << sizeof(BGRA<float>) << std::endl;
BGR<int> p;
p.r() = 25;
p.g() = 14;
p.b() = 58;
std::cout << p << std::endl;
std::cout << p[0] << " , " << p[1] << " , " << p[2] << std::endl;
std::cout << p.b() << " , " << p.g() << " , " << p.r() << std::endl;
BGR<int> q;
q = p;
std::cout << q[0] << " , " << q[1] << " , " << q[2] << std::endl;
BGR<int> res1;
res1 = q + p;
std::cout << res1.r() << " , " << res1.g() << " , " << res1.b() << std::endl;
BGR<int> res2;
res2 = q - p;
std::cout << res2.r() << " , " << res2.g() << " , " << res2.b() << std::endl;
BGRA<float> a;
a.r() = 255.0f;
a.g() = 0.0f;
a.b() = 0.0f;
a.a() = 128.5f;
BGRA<float> b = a;
std::cout << a << std::endl;
return 0;
}

character string to bitset in C++

I am still kind of new to C++ and am trying to figure out what I am not able to pass a value correctly to a bitset, at least I suspect that is what the problem is.
I wrote a small function to assist in flipping the bits of a hex value to reverse the endian. So example would be input 0x01 and it would return 0x80.
This is the code I wrote.
int flipBits(char msd, char lsd) {
char ch[5];
sprintf_s(ch, "0x%d%d", msd, lsd);
char buffer[5];
strncpy_s(buffer, ch, 4);
cout << ch << endl;
cout << buffer << endl;
bitset<8> x(buffer);
bitset<8> y;
for (int i = 0; i < 8; i++) {
y[i] = x[7 - i];
}
cout << y << endl; // print the reversed bit order
int b = y.to_ulong(); // convert the binary to int
cout << b << endl; // print the int
cout << hex << b << endl; // print the hex
return b;
}
I tried adding the strncpy because I thought maybe the null terminator from sprintf was not working properly with the bitset. If in the line
bitset<8> x(buffer);
I replace buffer with a hex value, say for example 0x01, then it works and prints out 0x80 as I would expect, but if I try to pass in the value with the buffer it doesn't work.
We can write a stl-like container wrapper such that we can write:
int main() {
std::bitset<8> x(0x01);
auto container = make_bit_range(x);
std::reverse(container.begin(), container.end());
std::cout << x << std::endl;
}
and expect the output:
10000000
full code:
#include <iostream>
#include <bitset>
#include <algorithm>
template<std::size_t N>
struct bit_reference {
bit_reference(std::bitset<N>& data, int i) : data_(data), i_(i) {}
operator bool() const { return data_[i_]; }
bit_reference& operator=(bool x) {
data_[i_] = x;
return *this;
}
std::bitset<N>& data_;
int i_;
};
template<std::size_t N>
void swap(bit_reference<N> l, bit_reference<N> r) {
auto lv = bool(l);
auto rv = bool(r);
std::swap(lv, rv);
l = lv;
r = rv;
}
template<std::size_t N>
struct bit_range {
using bitset_type = std::bitset<N>;
bit_range(bitset_type &data) : data_(data) {}
struct iterator {
using iterator_category = std::bidirectional_iterator_tag;
using value_type = bit_reference<N>;
using difference_type = int;
using pointer = value_type *;
using reference = value_type &;
iterator(bitset_type &data, int i) : data_(data), i_(i) {}
bool operator==(iterator const &r) const { return i_ == r.i_; }
bool operator!=(iterator const &r) const { return i_ != r.i_; }
iterator &operator--() {
return update(i_ - 1);
}
iterator &operator++() {
return update(i_ + 1);
}
value_type operator*() const {
return bit_reference<N>(data_, i_);
}
private:
auto update(int pos) -> iterator & {
i_ = pos;
return *this;
}
private:
bitset_type &data_;
int i_;
};
auto begin() const { return iterator(data_, 0); }
auto end() const { return iterator(data_, int(data_.size())); }
private:
bitset_type &data_;
};
template<std::size_t N>
auto make_bit_range(std::bitset<N> &data) {
return bit_range<N>(data);
}
int main() {
std::bitset<8> x(0x01);
auto container = make_bit_range(x);
std::reverse(container.begin(), container.end());
std::cout << x << std::endl;
}
also plenty of fun algorithms here: Best Algorithm for Bit Reversal ( from MSB->LSB to LSB->MSB) in C

c++ Unable to resolve overloaded function template

First, I don't understand why the compiler can't seem to resolve the offending code (wrapped by the ENABLE_OFFENDER macro). The two get() methods have very different call signatures. So, perhaps a c++ language lawyer could help explain why I'm getting the error.
Second, is there a way to provide more guidance to the compiler as to which get() it should use?
#include <iostream>
//switch offending code in/out
#define ENABLE_OFFENDER
/// Forward declare
template <typename T> class TableEntry;
/// Non-template base class
class TableEntryBase {
protected:
// prevent instantiation
TableEntryBase() { }
public:
virtual ~TableEntryBase() { }
template <typename T>
void set(const T& rvalue){
TableEntry<T>* entry = dynamic_cast<TableEntry<T> *>(this);
if(0 != entry){
entry->setValue(rvalue);
}
}
template <typename T>
T get(T& lvalue){
TableEntry<T>* entry = dynamic_cast<TableEntry<T> *>(this);
if(0 != entry){
return entry->getValue(lvalue);
} else {
return T();
}
}
template <typename T>
T get(){
TableEntry<T>* entry = dynamic_cast<TableEntry<T> *>(this);
if(0 != entry){
return entry->getValue();
} else {
return T();
}
}
};
template <typename T>
class TableEntry : public TableEntryBase {
private:
T m_value;
public:
TableEntry():TableEntryBase() { }
~TableEntry() { }
void setValue(const T& rvalue){
m_value = rvalue;
}
T getValue(T& lvalue){
lvalue = m_value;
return m_value;
}
T getValue(){
return m_value;
}
};
template <int N>
class Table {
private:
TableEntryBase* m_tableEntries[N];
int m_tableEntriesIndex;
public:
Table():m_tableEntriesIndex(0){}
virtual ~Table() { }
void addEntry(TableEntryBase* entry){
if(0 != entry)
m_tableEntries[m_tableEntriesIndex++] = entry;
}
template <typename T>
void setEntry(int entryIndex, const T& rvalue){
// I'm not sure why it's not set<T>(rvalue)
m_tableEntries[entryIndex]->set(rvalue);
}
template <typename T>
T getEntry(int entryIndex, T& lvalue){
return m_tableEntries[entryIndex]->get(lvalue);
}
#ifdef ENABLE_OFFENDER
template <typename T>
T getEntry(int entryIndex){
return m_tableEntries[entryIndex]->get();
}
#endif
};
int main(){
TableEntry<int> entry1;
// setting the value using base class set
entry1.set<int>(5);
TableEntry<double> entry2;
entry2.set<double>(3.14);
std::cout << "entry1 value = " << entry1.getValue() << std::endl;
std::cout << "entry2 value = " << entry2.getValue() << std::endl;
std::cout << "entry1 value = " << entry1.get<int>() << std::endl;
std::cout << "entry2 value = " << entry2.get<double>() << std::endl;
TableEntryBase* entry_ptr = &entry1;
std::cout << "entry1 value = " << entry_ptr->get<int>() << std::endl;
Table<2> table;
table.addEntry(&entry1);
table.addEntry(&entry2);
table.setEntry<int>(0, 10);
std::cout << "entry1 value = " << entry1.get<int>() << std::endl;
std::cout << "entry2 value = " << entry2.get<double>() << std::endl;
int val3 = 0;
int val4 = 0;
val4 = table.getEntry<int>(0, val3);
int val5 = 0;
#ifdef ENABLE_OFFENDER
val5 = table.getEntry<int>(0);
#endif
std::cout << "val3 = " << val3 << ", val4 = " << val4 << ", val5 = " << val5 << std::endl;
return 0;
}
/* GCC error
main.cpp:129:30: instantiated from here
main.cpp:96:95: error: no matching function for call to ‘TableEntryBase::get()’
main.cpp:96:95: note: candidates are:
main.cpp:26:4: note: template<class T> T TableEntryBase::get(T&)
main.cpp:36:4: note: template<class T> T TableEntryBase::get()
*/
I got the code to work on my older compilers by changing the offending code as such.
#ifdef ENABLE_OFFENDER
template <typename T>
T getEntry(int entryIndex){
// Error: expected primary-expression before ‘>’ token
//return m_tableEntries[entryIndex]->get<T>();
// Error: couldn't deduce template parameter ‘T’
//return m_tableEntries[entryIndex]->get();
TableEntryBase* entry = m_tableEntries[entryIndex];
return entry->get<T>();
}
#endif