Created
April 24, 2019 07:44
-
-
Save eric-wieser/ed8e54d6ec78f973bdb821562fd386c7 to your computer and use it in GitHub Desktop.
Output parameters with implicit casting
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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