Skip to content

Instantly share code, notes, and snippets.

@eric-wieser
Created April 24, 2019 07:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eric-wieser/ed8e54d6ec78f973bdb821562fd386c7 to your computer and use it in GitHub Desktop.
Save eric-wieser/ed8e54d6ec78f973bdb821562fd386c7 to your computer and use it in GitHub Desktop.
Output parameters with implicit casting
#include <utility>
template<typename T, typename U>
class out_arg;
/** Use in a parameter list for an output argument. Can only be assigned to. */
template<typename T>
class out_param {
private:
T& val;
constexpr out_param(T& val) : val(val) {}
public:
T& operator=(T&& v) {
return val = std::forward<T>(v);
}
template<typename T2, typename U>
friend class out_arg;
};
/** Use in a function call to perform a cast in the output argument */
template<typename T, typename U>
class out_arg {
private:
T val;
U& target;
public:
constexpr out_arg(U& target) : target(target) {}
~out_arg() {
target = std::move(val);
}
operator out_param<T>() && {
return out_param<T>(val);
}
};
/** Optimization of the above */
template<typename U>
class out_arg<U, U> {
private:
U& target;
public:
constexpr out_arg(U& target) : target(target) {}
operator out_param<U>() && {
return out_param<U>(target);
}
};
/** Type-deducing shorthand */
template<typename T, typename U>
out_arg<T, U> out(U& target) {
return out_arg<T, U>(target);
}
void foo(out_param<int> a);
int type_matches() {
int b;
foo(out<int>(b));
return b;
}
long long type_mismatches() {
long long b;
foo(out<int>(b));
return b;
}
long long type_mismatches_manual() {
int a;
long long b;
foo(out<int>(a));
b = a;
return b;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment