[C++-sig] Calling a C++ function with arguments by reference (lvalues)

Nat Goodspeed nat at lindenlab.com
Mon Aug 2 17:24:22 CEST 2010


Oded Padon wrote:

> The C++ code is:
> 
> void add(int const a, int const b, int const& c)
> {
>     c = a + b;
> }

This doesn't even compile under g++ 4.0.1 (Mac):
error: assignment of read-only reference 'c'

I hope you're not using a compiler that accepts such code as legal?

> I must emphasize that I wish to have functions that get arguments
 > by reference and change them. Returning the values using the return
 > mechanism isn't what I want to do (I have functions that get and set
 > many many arguments, and I hardly wish to rewrite them).

<boring anecdote>

Many moons ago I had the dubious pleasure of using a FORTRAN compiler 
that was old and dumb even for the time. With this compiler, all 
parameters were passed by non-const reference. One of my team was 
delegated to write a subroutine that accepted certain parameters. There 
was miscommunication about the expected parameter order, and the calling 
code ended up passing the integer literal '5' in the parameter slot to 
which the subroutine stored its result.

 From that point on, everywhere the literal '5' appeared in the source, 
the executable was instead referencing the result of some computation.

Merriment ensued as the program confounded all attempts to predict its 
behavior.

You are proposing to do the same to the Python interpreter. It's 
appropriate for Boost.Python to try to make that difficult.

</boring anecdote>

Suppose you were writing this code from scratch in pure Python. How 
would you approach the problem? This won't work:

def add(a, b, c):
     c = a + b

def caller():
     c = 0
     add(1, 2, c)
     assert c == 3   # FAIL

One way would be to keep some set of working variables in an object, and 
pass that object into the function that wants to modify them:

class Vars(object):
     def __init__(self):
         self.a = 0
         self.b = 0
         self.c = 0

def add(a, b, vars):
     vars.c = a + b

def caller():
     v = Vars()
     add(1, 2, v)
     assert v.c == 3

Or you could keep working values in a dict, if you prefer dict lookup to 
attribute references.

You can code your C++ add() function to accept its 'vars' parameter as a 
boost::python::object. If you pass a class object, you can reference 
vars.attr("c"). If you pass a dict, you can reference vars["c"].

See also: 
http://www.boost.org/doc/libs/1_43_0/libs/python/doc/tutorial/doc/html/python/embedding.html#python.using_the_interpreter 



More information about the Cplusplus-sig mailing list