Skip to content

Instantly share code, notes, and snippets.

@lambdageek
Last active November 30, 2018 23:41
Show Gist options
  • Save lambdageek/4cb2321485d5fe3410f2413a8e9914d1 to your computer and use it in GitHub Desktop.
Save lambdageek/4cb2321485d5fe3410f2413a8e9914d1 to your computer and use it in GitHub Desktop.
Explicit ref and out keywords for arguments in C++11
#include <utility>
#include <functional>
#include <stdio.h>
template <typename U>
struct Out {
explicit Out (U& u_) : u (u_) {}
Out (const Out<U>& other) = default;
Out (Out<U>&& other) = default;
Out<U>& operator= (const Out<U>&) = delete;
const Out<U>& operator= (const U& u_) const {
u = u_;
return *this;
}
const Out<U>& operator= (U&& u_) const {
using std::move;
u = move (u_);
return *this;
}
private:
U& u;
};
template <typename U>
struct Ref {
explicit Ref (U& u_) : u (u_) {}
Ref (const Ref<U>& other) = default;
Ref (Ref<U>&& other) = default;
Ref (const std::reference_wrapper<U>& other) : u (&other.get ()) {}
Ref<U>& operator= (const Ref<U>&) = delete;
const Ref<U>& operator= (const U& u_) const {
u = u_;
return *this;
}
const Ref<U>& operator= (U&& u_) const {
using std::move;
u = move (u_);
return *this;
}
operator U& () const {
return u;
}
private:
U& u;
};
template<typename U>
inline
Out<U> out (U& u)
{
return Out<U>(u);
}
template<typename U>
inline
Out<U> out (U& u)
{
return Out<U>(u);
}
void
foo (Ref<int> x, Out<int> z)
{
x = 1;
int y = x; // int y = z is a compile-time error
printf ("%d\n", y);
z = 3;
x += 1; // z += 1 is a compile-time error
}
int
main ()
{
using std::ref;
int x = 0;
int z = 0;
foo (ref (x), out(z));
printf ("%d %d\n", x, z);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment