In C#, passing a parameter by reference can't be ignored:
// C#
void foo(ref int p_value) ; // passing an int by reference
void bar()
{
int i = 0 ;
foo(ref i) ;
}
In C++ (and as far as I am concerned, it is a good thing), the passing by reference is only marked in the function prototype, so the code above becomes:
// C++
void foo(int & p_value) ; // passing an int by reference
void bar()
{
int i = 0 ;
foo(i) ; // at call site, there is no "ref" marker.
}
The thing is, for a few special functions, to ease code reviewing, we would want to use a C#-like solution to read at call site if a variable is expected to be modified or not.
I devised a solution wrapping the value with a struct, something like:
template<typename T>
struct Ref
{
T & m_value ;
explicit Ref(T & p_value) : m_value(p_value) {}
operator T & () { return this->m_value ; }
operator const T & () const { return this->m_value ; }
} ;
template <typename T> // wrapping T with Ref
Ref<T> byRef(T & p_value)
{
return Ref<T>(p_value) ;
}
template <typename T> // idempotent-enabling overload (no need for Ref<Ref<T>>)
Ref<T> & byRef(Ref<T> & p_value)
{
return p_value ;
}
I expect this trivial code to be inlined away in optimized code.
This enables me to write the code:
void foo(Ref<int> p_int)
{
p_int *= 10 ;
}
void bar()
{
int i = 0 ;
foo(byRef(i)) ;
}
Which is exactly what I want:
- no use of
foo(& i)
C-style notation, with pointers, needing to handle NULL, etc. - in the cases we care, we can see in the code what is passed by non-const reference
Did I miss some unexpected problem/hidden cost that will come back to bite me in a few weeks/months/years?
Could this code be written better?
Will the code be confusing when seen through some un*x debuggers?
P.S.: Of course, Ref
and byRef
will be properly namespaced. I'm still not sure about making Ref::m_value
public or private.