When writing overloads for r-value I often end up with the same code. So to avoid repetition I use this trick
void f(int&&) {
std::println("&& overload");
}
void f(int const&) {
std::println("const& overload");
}
template<typename T1, typename T2>
concept no_repetition = std::same_as<std::remove_cvref_t<T1>, T2>;
void test(no_repetition<int> auto&& val) {
f(std::forward<decltype(val)>(val));
}
int main( ) {
int lval = 0;
test(0); //prints && overload
test(lval); //prints const& overload
return 0;
}
I am curious whether this approach has caveats. And if it does how can work around them.
You may have oversimplified your question, but in your example the
test()function is more restrictive than thef(...)functions. Specifically:You can rewrite your function using universal references:
which will behave the same way as the
f(...)functions:If you do want your
test()function to have a hard constraint onint, then you have already come up with the best solution. In your comments you've mentioned that you don't understand how it works, so here is a quick explanation. If you have a concept, say:you can write an abbreviated function-template, like you did:
This is equivalent to:
Notice that in the above example (as well as in the abbreviated function-template) you specify one less parameter in
Uref<int>because the deduced type (Int) is implicitly substituted as the first parameter toUref.You could also re-write the above in a more verbose form:
Link to working example: https://godbolt.org/z/76hP3P5zz