I have a vector containing values of a given primitive type, but I want to iterate this vector such that I can perform certain operations "as if" working with a class that wraps the value type.
The following code example compiles and produces the expected result:
#include <iostream>
#include <vector>
template<class T>
struct wrap
{
T x;
void print() const
{
if (x < 0)
std::cout << " negative ";
else if (x > 0)
std::cout << " positive ";
else
std::cout << " --null-- ";
}
void operator ++ ()
{
if (this->x < static_cast<T>(0))
this->x += static_cast<T>(1000);
}
};
int main()
{
using vec_t = std::vector<int>;
vec_t v;
v.push_back(-1234);
v.push_back( 5678);
v.push_back(-4);
v.push_back(0);
// essential piece of code
using vec_w = std::vector< wrap<int> >;
vec_w::iterator it = reinterpret_cast<vec_w*>(&v)->begin();
vec_w::iterator ti = reinterpret_cast<vec_w*>(&v)->end();
while (it != ti)
{
it->print();
++(*it);
it->print();
std::cout << std::endl;
++it;
}
return 0;
}
Output:
negative negative
positive positive
negative positive
--null-- --null--
But is this safe to use, as long as the wrapper defines the exact same value type (and nothing else)?
But is this safe to use, as long as the wrapper defines the exact same value type (and nothing else)?
No. You are breaking the strict aliasing rule.
Why not wrap T&
?
template<class T>
struct wrap
{
T& x;
void print() const
{
if (x < 0)
std::cout << " negative ";
else if (x > 0)
std::cout << " positive ";
else
std::cout << " --null-- ";
}
void operator ++ ()
{
if (this->x < static_cast<T>(0))
this->x += static_cast<T>(1000);
}
};
You can wrap in a loop
int main()
{
std::vector<int> v;
v.push_back(-1234);
v.push_back( 5678);
v.push_back(-4);
v.push_back(0);
for (auto & i : v)
{
wrap<int> w { i };
w.print();
++w;
w.print();
std::cout << std::endl;
}
return 0;
}
Or have a vector of wrapped
int main()
{
std::vector<int> v;
v.push_back(-1234);
v.push_back( 5678);
v.push_back(-4);
v.push_back(0);
std::vector<wrap<int>> w { v.begin(), v.end() };
for (auto & i : w)
{
i.print();
++i;
i.print();
std::cout << std::endl;
}
return 0;
}