I am trying to overload the insertion operator '<<' to simplify some syntax required to use a specific piece of software. That software implements a hash object which holds a variety of types of data, so type checking cannot be done at compile-time because the type of the RHS of a given expression is not known until run-time. This hash is very similar in spirit to Boost Property Trees.
I am trying to write this as a template function to extract data from the hash. This works just fine as long as the receiving variable already exists (is initialized). It fails to compile if this is used during variable initialization.
So, this compiles and works fine.
int value;
value << data;
But this does not compile at all.
int value << data;
The real code is quite large and complex so I have written the following simplified program to exhibit the same behaviors.
I am using gcc version 4.3.4. A different compiler is not an option.
Any and all help is appreciated.
#include <iostream>
/**
* Simple class to use with the templates.
*/
class Data
{
public:
Data ()
{
m_value = 0;
}
Data (int val)
{
m_value = val;
}
~Data ()
{
}
int value ()
{
return (m_value);
}
int value (int val)
{
m_value = val;
return (value ());
}
private:
int m_value;
};
/**
* Assign data from RHS to LHS.
*/
template <class T>
void operator<< (T &data, Data &node)
{
data = node.value ();
}
/**
* Simple test program.
*/
int main (int argc, char *argv[])
{
// initialize the data
Data data (123);
std::cout << data.value () << std::endl;
// extract the data and assign to integer AFTER initialization
int value;
value << data;
std::cout << value << std::endl;
// extract the data and assign to integer DURING initialization
// *** problem is here ***
int other << data; // <-- this fails to compile with...
// expected initializer before '<<' token
std::cout << other << std::endl;
return (0);
}
int value << data; does not make grammatical sense.
Think of << as being like any other operator, rather like +=. Yes, << is overloaded but it still has to obey the same semantics as its natural incarnation as a bitwise shift.
int value += 3; for example, makes no sense either.
int value << data; is not valid C++.
Related
I am trying to track the value of a variable that I will input in an API function.
One option is to overload the assignment operator and put some code there. But how would I overload an assigment operator on a member variable of a class?
#include <iostream>
using namespace std;
template <class T>
class MonitoredVariable1
{
public:
MonitoredVariable1() { }
MonitoredVariable1(const T& value) : m_value(value) {}
operator T() const { return m_value; }
T val;
T& operator = (const T& value)
{
val = value;
m_value = value;
std::cout << "value updated" << " \n"; //THIS NEVER GET PRINTED!!!
return val;
}
private:
T m_value;
};
int main()
{
MonitoredVariable1<double> MonitoredVariable;
MonitoredVariable.val = 10.2;
std::cout << "main done..." << " \n";
return 0;
}
To monitor changes to the variable, you need to be assigning to the class, not the contained variable.
First, get rid of val. Only have the private m_value value. This way all accesses have to go thru your member functions that can track the changes.
operator= should return a reference to the class (return *this;), not the value.
Assignment is to the class object:
MonitoredVariable = 10.2;
You can only overload assignment on a class. But you can make that variable to be of a class type with overloaded assignment, like:
class Monitor {
class Monitored {
double x;
public:
Monitored &operator= (double v) {
std::cout << "Assigned " << v << std::endl;
x = v;
return *this; // don’t forget this!
}
operator double() const {
std::cout << "Accessed " << x << std::endl;
return x;
}
};
Monitored val;
};
You may need to overload more operators, and also to pass a reference to Monitor into val (there are tricks to calculate it instead if you’re short on memory).
You can (in modern C++) even overload the & operator, but unless the API function is a template, it has to return pointer. Watching for access through it is very environment-specific.
During debugging, you can usually set a memory watchpoint that will pause program execution on writing to, or even on reading from, a particular memory location (for GDB, see Setting Watchpoints; VS should have a similar feature). That requires hardware support (or debugger-interpreter which is insanely slow), though, so the overall number of watchpoints is often very limited.
Without a debugger, you may be able to make a one-shot watch using memory protection tricks (like protecting the page containing the variable, and unprotecting it on first SEGV) but that’s all too fragile for normal use.
I am implementing a device_vector in Cuda and i am taking ideas from the well known library Thust.
Now for accessing and modifying an element in that device_vector (v), I need to do v[N] = x. For that i need to overload the [] operator.
This is the code used to overload the [] operator :
T& operator[] (unsigned int index)
{
if (index >= numEle)
return ptr[0];
else
return ptr[index];
}
The problem is : To modify any memory location in Device Memory, we need to make a Cuda Kernel Call and a Cuda kernel call cannot return anything.
As far the [] overloading is concerned it returns the reference to the element we want to modify.
How can we do this for a Cuda Kernel ?
Note : I know Thrust Library somehow does this but I am not able to understand how.
The comments have very good pointers, but as an example, you can create an object that will allow you to use the [] operator to write to the CUDA array directly (or do any other things you choose):
struct CudaVector {
unsigned int get(unsigned int index) {
cout << "Get from device: " << index << endl;
return 0; // TODO read actual value
}
void set(unsigned int index, unsigned int value) {
cout << "Set in device: " << index << " " << value << endl;
// TODO write actual value
}
struct Item {
CudaVector& vector;
unsigned int index;
operator unsigned int() const {
return vector.get(index);
}
unsigned int operator=(unsigned int other) {
vector.set(index, other);
return other;
}
unsigned int operator=(const Item& other) {
return (*this = static_cast<unsigned int>(other));
}
};
Item operator[](unsigned int index) {
return Item{*this, index};
}
};
This works like:
CudaVector vector;
unsigned int foo = vector[8];
vector[5] = vector[6] = vector[7];
Output:
Get from device: 8
Get from device: 7
Set in device: 6 0
Set in device: 5 0
Idea is that your operator[] doesn't return a reference, but instead it returns a temporary object that is able to handle 'reads' (using the conversion operator) and 'writes' (using the assignment operator).
(The second overload is there to allow chained assignments, since the first one won't be picked up automatically if you don't assign from unsigned int first.)
I have a class that I use to keep track of the values assumed by a variable. I implemented it by overloading operator=.
Usage example:
myType var0;
var0 = 1;
var0 = 3;
generates on stdout:
1
3
This works fine with variables, but not with arrays. How can I extend this feature?
One way would be overloading the [] operator to return a "proxy" - an object that references your variable, and overloads the = operator to do the tracking.
Here is a sample implementation:
#include <iostream>
using namespace std;
struct myArray;
class proxy {
myArray &array;
int index;
public:
proxy(myArray &_array, int _index)
: array(_array)
, index(_index) {
}
proxy& operator=(int value);
operator int() const;
};
struct myArray {
int data[100];
proxy operator[](int index) {
return proxy(*this, index);
}
};
proxy& proxy::operator=(int value) {
cout << "Asigning " << value << " to element " << index << endl;
array.data[index] = value;
return *this;
}
proxy::operator int() const {
cout << "Reading element at " << index << endl;
array.data[index];
}
int main() {
myArray a;
a[5] = 123;
a[8] = 321;
int x = a[5];
return 0;
}
This prints
Asigning 123 to element 5
Asigning 321 to element 8
Reading element at 5
What you want to do is to use a proxy class for your array and on that class define an operator[] function. Much like how std::vector does it.
You would trace when a non-const reference is produced to an array element. I think that you'd have to assume it was about to be written to. You would make the array out of your existing class so that you'd see the actual write.
The output might look like:
ref to element 32: write 1
Or however you would like it.
Well, arrays don't support operator= anyway, so that is not a real a problem. You can assign to individual array elements of course, but that's already covered by your existing operator=.
You could create a MyArrayType that overloads the [] operator to store the values internally within an array of MyTypes
I am confused when all the code I find shows returning a reference variable when overloading the prefix operator. I went through the parashift.com FAQ (http://www.parashift.com/c++-faq-lite/operator-overloading.html#faq-13.14) and it isn't clear, even though it says it WILL be clear when you read it. I adapted their example into a nonsensical, pointless little program to test.
#include<iostream>
using namespace std;
class Number {
public:
Number& operator++ (); // prefix ++
Number operator++ (int); // postfix ++
int value() { return value_; }
void setValue(int value) { value_ = value; }
private:
int value_;
};
Number& Number::operator++ () {
++value_;
return *this;
}
Number Number::operator++ (int unused) {
Number temp;
temp.setValue(value_);
++value_;
return temp;
}
int main()
{
Number someNum;
someNum.setValue(20);
cout << "someNum : " << someNum.value() << "\n";
someNum++;
++someNum;
cout << "someNum : " << someNum.value() << "\n";
return 0;
}
The problem is, it works if I just declare it as a Number object as well like so:
#include<iostream>
using namespace std;
class Number {
public:
Number operator++ (); // prefix ++
Number operator++ (int); // postfix ++
int value() { return value_; }
void setValue(int value) { value_ = value; }
private:
int value_;
};
Number Number::operator++ () {
++value_;
return *this;
}
Number Number::operator++ (int unused) {
Number temp;
temp.setValue(value_);
++value_;
return temp;
}
int main()
{
Number someNum;
someNum.setValue(20);
cout << "someNum : " << someNum.value() << "\n";
someNum++;
++someNum;
cout << "someNum : " << someNum.value() << "\n";
return 0;
}
I assume I simply need a better understanding of reference variables. Can anyone explain simply why the prefix operator SHOULD be coded as returning a reference variable?
The difference between :
Number& Number::operator++ () {
++value_;
return *this;
}
and
Number Number::operator++ () {
++value_;
return *this;
}
is that, when you use the first code, the following expression:
++(++(++someNum));
increments someNum THRICE. See the output here: http://ideone.com/y9UlY
However, when you use the second one, this
++(++(++someNum));
increments someNum just ONCE!! See the output here: http://ideone.com/eOLdj
It is because when you return the reference from operator++(), the second and third ++ invokes on the same object called someNum and therefore, it increments the same object, all the times. But when you return by value, the second and third ++ invokes on the temporary object which you returned from operator++(). Hence, the second and third call doesn't increment someNum, instead it increments the temporary objects which get destroyed at the end of the expression.
Now if the temporary objects get destroyed, why create then in the first place? After all, its pre-increment operator, which means the temporary and the original object will have the same value. So the good design decision is, return by reference when defining pre-increment operator, to avoid creating temporary, and improve performance.
First, there's an efficiency issue. You are creating a new instance of the class in order to return it for no reason.
Second, there's the semantic issue. Your code invokes the empty constructor or the copy constructor to make the temporary and then destructs the temporary. If that has semantic meaning that's inappropriate, then the code doesn't really work, it just appears to.
Third, the code returns the wrong thing. Consider: ++foo.do_something();. With your code, we call 'do_something' on the temporary object. We wanted to call do_something() on the pre-incremented foo.
My target was to make properties in C++ like in C# - with non-trivial set/get behavior.
Here, object of Property holds refs to master of the prop and its set/get methods.
Realisation, content of Property.h:
#include <iostream>
using namespace std;
namespace First {
template <class Master, class Type>
struct Property
{
Master &master;
const Type (Master::*&get) () const;
Type (Master::*&set)(Type value);
Property
(
Master &master,
const Type (Master::*get) () const,
Type (Master::*set)(Type value)
):
get(get),
set(set),
master(master)
{ }
operator const Type() const { cout << "inside" << endl; return (master.*get)(); }
Type operator = (Type value)
{
return (master.*set)(value);
}
};
// Test chamber.
class R
{
float x;
const float getx() const { cout << "returning " << 0 << endl; return 0; }
float setx(float value) { cout << "setting " << value << " in place of " << x << endl; return x = value; }
public:
Property<R, float> X;
R(): X(*this, &R::getx, &R::setx) { }
};
}
I also created .cpp file:
#include "Property.h"
using namespace First;
int main()
{
R r;
r.X = 10;
float y = r.X;
}
The program makes "assign" step, printing 'setting 0 to 10', but segfaults on call to "retrieve" step, no difference what code (or no at all) inside 'R::getx()'.
~/Sources$ ./a.out
setting 10 in place of 0
inside
zsh: segmentation fault ./a.out
It seems that call to (master.*get()) itself causes a failure. What is wrong in this code?
UPD: A tested out that any other call to master's functions leads to segfault, only one call of (master.*set) successes. Seems that this call invalidates state of object, member-to-ptr, Property itself or Moon phase.
const Type (Master::*&get) () const;
Type (Master::*&set)(Type value);
Remove & from the above definitions. Because of &, each of these bound to the constructor parameters which do not exist after the constructor returns.
Also note that it seems that (master.*set)(value) works, its because you're unlucky. Its actually invokes undefined behavior. But you're lucky that very soon you come to know the problem when (master.*get)() fails, giving segfault.
Use:
const Type (Master::*get) () const;
Type (Master::*set)(Type value);
It should work now, without any problem, as it would cause copy of the addresses in the initialization-list, rather than referring to the parameters!
segfault : http://ideone.com/46RrU (your original code)
no fault : http://ideone.com/PljI4 (after fixing)