Redefine a single operator of a defined type. C++ - c++11

I want to redefine the bit shift operator on a 64 bit unsigned integer in c++ in such a way that I can do say, x<<d, where x is a 64 bit integer and d is an integer with |d|<64, to make it equivalent to x<<d for d>0 and x>>|d| for d<0.
The only way I know how to do this is to define a whole new class and overload the << operator, but I think that also means I need to overload all the other operators I need (unless there is a trick I don't know), which seems a bit silly considering I want them to behave exactly as they do for the pre-defined type. It's just the bitshift that I want to change. At present, I have just written a function called 'shift' to do this, which doesn't seem very c++ ish, even though it works fine.
What is the stylistically correct way to do what I need?
Thanks

If you were able to do this, it would be very confusing to other C++ programmers who read your code and see:
int64 x = 92134;
int64 y = x >> 3;
And have it behave differently than their expectations, and behave differently from what the C++ standard defines.
The stylistic choice that agrees most with the C++ code I've seen is to continue using your own myshift() function.
int64 y = myshift(x, 3);

I think it's very horrible (and I propose it just for fun) but... if you accept to wrap the number of bit shifted in a struct...
#include <iostream>
struct foo
{ int num; };
long long int operator<< (const long long int & lli, const foo & f)
{
int d { f.num };
if ( d < 0 )
d = -d;
if ( d >= 64 )
d = 0;
return lli << d;
}
int main()
{
long long int lli { 1 };
std::cout << (lli << foo{+3}) << std::endl; // shift +3
std::cout << (lli << foo{-3}) << std::endl; // shift +3 (-3 -> +3)
std::cout << (lli << foo{+90}) << std::endl; // no shift (over 64)
std::cout << (lli << foo{-90}) << std::endl; // no shift (over 64)
return 0;
}

Related

Is it possible to place a std::array at a fixed memory address?

For an embedded design I want to place a C++ std::array at a specific memory address, which points to a buffer shared by hardware and software. Is this possible?
Try Placement new:
#include <array>
#include <iostream>
int main()
{
alignas(double) char buffer[100];
auto parr = new (buffer) std::array<double, 3> {3.14, 15.161, 12};
const auto & arr = *parr;
std::cout << (void*) &arr << " " << (void*) buffer << "\n";
for (auto x: arr)
std::cout << x << " ";
std::cout << "\n";
}
which may give this output:
0x7ffcdd906770 0x7ffcdd906770
3.14 15.161 12
One thing to be worried about is whether the address you want to use is consistent with the alignment requirements of the data you want to hold in the array. Most likely you will be dealing with chars, floats or ints, so this condition shouldn't be difficult to enforce.
For embedded code, two simple solutions spring to mind:
Declare extern int myArray[1234] ; and then define myArray (or rather its mangled form) in your linker definition file.
Define a macro: #define myArray ((int*)0xC0DEFACE)
The first solution is for the purists; the second is for the pragmatists.

Can we add two objects by overloading - operator

#include<iostream>
using namespace std;
class Complex {
private:
int real, imag;
public:
Complex(int r = 0, int i =0) {real = r; imag = i;}
Complex operator-(Complex const &obj) {
Complex res;
res.real = real + obj.real;
res.imag = imag + obj.imag;
return res;
}
void print() {
cout << real << " + i" << imag << endl;
}
};
int main()
{
Complex c1(10, 5), c2(2, 4);
Complex c3 = c1 - c2;
c3.print();
}
I am using operator - to add two objects
I am changing the main functionality of the - sign.
This code is running perfectly and adding the real and imaginary part together
Yes, any behavior can be given to the operators.
The recommendation is, however, to avoid overloading operators unless they have the usual meaning.
Sometimes libraries use operators to create small Domain Specific Languages (DSLs), but one must balance brevity and readability.

C++ comma operator

I'm trying to run this code from C++ Primer plus
#include <iostream>
using namespace std;
int main() {
int i = 20, j= 2*i;
cout << "i = " << i << endl;
int cats = 17,240; //No, I don't want the number 17240
return 0;
}
Why I'm seeing this error expected unqualified-id before numeric constant int cats = 17,240; , I don't know, I need a short explanation. Thanks
int cats = 17,240; would be viewed by the compiler as int (cats = 17),240; due to operator precedence. And int 240; makes no sense, so a compiler diagnostic is issued.
Did you want 17240 cats? If so then drop the comma.

Computed Members in C++ Class by Empty Struct Members With Overloaded Implicit Conversions

In some data structures, it would be useful to have members whose values are computed from the other data members upon access instead of stored.
For example, a typical rect class might store it's left, top, right and bottom coordinates in member data fields, and provide getter methods that return the computed width and height based on those values, for clients which require the relative dimensions instead of the absolute positions.
struct rect
{
int left, top, right, bottom;
// ...
int get_width() const { return right - left; }
int get_height() const { return bottom - top; }
};
This implementation allows us to get and set the absolute coordinates of the rectangles sides,
float center_y = (float)(box.top + box.bottom) / 2.0;
and additionally to get it's relative dimensions, albeit using the slightly different method-call operator expression syntax:
float aspect = (float)box.get_width() / (float)box.get_height();
The Problem
One could argue, however, that it is equally valid to store the relative width and height instead of absolute right and bottom coordinates, and require clients that need to compute the right and bottom values to use getter methods.
My Solution
In order to avoid the need to remember which case requires method call vs. data member access operator syntax, I have come up with some code that works in the current stable gcc and clang compilers. Here is a fully functional example implementation of a rect data structure:
#include <iostream>
struct rect
{
union {
struct {
union { int l; int left; };
union { int t; int top; };
union { int r; int right; };
union { int b; int bot; int bottom; };
};
struct {
operator int() {
return ((rect*)this)->r - ((rect*)this)->l;
}
} w, width;
struct {
operator int() {
return ((rect*)this)->b - ((rect*)this)->t;
}
} h, height;
};
rect(): l(0), t(0), r(0), b(0) {}
rect(int _w, int _h): l(0), t(0), r(_w), b(_h) {}
rect(int _l, int _t, int _r, int _b): l(_l), t(_t), r(_r), b(_b) {}
template<class OStream> friend OStream& operator<<(OStream& out, const rect& ref)
{
return out << "rect(left=" << ref.l << ", top=" << ref.t << ", right=" << ref.r << ", bottom=" << ref.b << ")";
}
};
/// #brief Small test program showing that rect.w and rect.h behave like data members
int main()
{
rect t(3, 5, 103, 30);
std::cout << "sizeof(rect) is " << sizeof(rect) << std::endl;
std::cout << "t is " << t << std::endl;
std::cout << "t.w is " << t.w << std::endl;
std::cout << "t.h is " << t.h << std::endl;
return 0;
}
Is there anything wrong with what I am doing here?
Something about the pointer-casts in the nested empty struct types' implicit conversion operators, i.e. these lines:
return ((rect*)this)->r - ((rect*)this)->l;
feels dirty, as though I may be violating good C++ style convention. If this or some other aspect of my solution is wrong, I'd like to know what the reasoning is, and ultimately, if this is bad practice then is there a valid way to achieve the same results.
One thing that I would normally expect to work doesn't:
auto w = t.w;
Also, one of the following lines works, the other does not:
t.l += 3;
t.w += 3; // compile error
Thus, you have not changed the fact that users need to know which members are data and which are functions.
I'd just make all of them functions. It is better encapsulation anyway. And I would prefer the full names, i.e. left, top, bottom, right, width and length. It might be a few more characters to write, but most code is read much more often than it is written. The extra few characters will pay off.

Boost muliprecision cpp_dec_float compare only to desired precision

I am using the boost::multiprecision library for decimal float types, and wish to compare two floats to the specified precision.
However, cpp_dec_float seems to compare the number not to the specified precision, but also includes the guard digits:
#include <iostream>
#include <boost/multiprecision/cpp_dec_float.hpp>
//#include <boost/math/special_functions.hpp>
typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<50> > flp_type;
int main(int argc, char* argv[])
{
// 50 decimal digits
flp_type sqrt2("1.4142135623730950488016887242096980785696718753769");
// Contains calculated guard digits
flp_type result(boost::multiprecision::sqrt(flp_type("2")));
// The 50 digits of precision actually ompare equal
std::cout << std::setprecision(50) << sqrt2 << std::endl;
std::cout << std::setprecision(50) << result << std::endl;
// I want this to compare to the specified precision of the type, not the guard digits
std::cout << (result==sqrt2) << std::endl;
return 0;
}
Output:
1.4142135623730950488016887242096980785696718753769
1.4142135623730950488016887242096980785696718753769
0
Expected:
1.4142135623730950488016887242096980785696718753769
1.4142135623730950488016887242096980785696718753769
1
See on Coliru
I have tried to "truncate" with precision(), but to no avail.
Is there a way to compare the two numbers without resorting to epsilon comparisons?
If you strip the guard bits, you effectively cripple the fidelity of the type as intended.
A surefire way would be to use (de)serialization, really.
So I suggest
Live On Coliru
// Either
std::cout << std::numeric_limits<flp_type>::epsilon() << "\n";
std::cout << (abs(result-sqrt2) < std::numeric_limits<flp_type>::epsilon()) << std::endl;
// Or
result = flp_type { result.str(49, std::ios::fixed) };
std::cout << (result==sqrt2) << std::endl;
Note that the epsilon is 1e-49 there
Prints
1.4142135623730950488016887242096980785696718753769
1.4142135623730950488016887242096980785696718753769
1e-49
1
1
Obviously the epsilon() based comparison would be appear the more efficient
bool is_equal = abs(result-sqrt2) < std::pow(10, -std::numeric_limits< flp_type >::digits10 );

Resources