Example
auto foo(auto&&);
int main() {
int i{};
const int c{};
foo(42); // int
foo(i); // int&
foo(int{i}); // int
foo(auto{i}); // int
foo(auto(42)); // int
foo(c); // const int&
foo(int{c}); // int
foo(auto(c)); // int
}
Puzzle
- Can you implement C++20/C++23 version of
copy_and_sum_ts
which copies and sums given parameters...?
struct copy {
bool copied{};
constexpr copy() = default;
constexpr copy(const copy&) : copied{true} {}
constexpr operator auto() const { return copied; }
};
namespace cpp20 {
constexpr auto copy_and_sum_ts(auto&... ts); // TODO
}
namespace cpp23 {
constexpr auto copy_and_sum_ts(auto&... ts); // TODO
}
int main() {
constexpr copy c1, c2, c3;
static_assert(0 == cpp20::copy_and_sum_ts());
static_assert(1 == cpp20::copy_and_sum_ts(c1));
static_assert(2 == cpp20::copy_and_sum_ts(c1, c2));
static_assert(3 == cpp20::copy_and_sum_ts(c1, c2, c3));
static_assert(0 == cpp23::copy_and_sum_ts());
static_assert(1 == cpp23::copy_and_sum_ts(c1));
static_assert(2 == cpp23::copy_and_sum_ts(c1, c2));
static_assert(3 == cpp23::copy_and_sum_ts(c1, c2, c3));
}
Solutions
namespace cpp20 {
namespace detail {
constexpr auto clone(const auto & t) { return t; }
} // namespace detail
constexpr auto copy_and_sum_ts(auto &...ts) {
return (0 + ... + detail::clone(ts));
}
} // namespace cpp20
namespace cpp23 {
constexpr auto copy_and_sum_ts(auto &...ts) {
return (0 + ... + auto{ts});
}
} // namespace cpp23
namespace cpp20 {
constexpr auto copy_and_sum_ts(auto&... ts) {
return (copy{} + ... + copy{ts});
}
}
namespace cpp23 {
constexpr auto copy_and_sum_ts(auto&... ts) {
return (copy{} + ... + auto{ts});
}
}
namespace cpp20 {
constexpr auto copy_and_sum_ts(auto&... ts){
auto sum = 0;
auto copier = [](auto& ts) {
auto copy = ts;
return copy;
};
return (0 + ... + copier(ts));
};
}
namespace cpp23 {
constexpr auto copy_and_sum_ts(auto&... ts){
return (0 + ... + auto{ts});
};
}
namespace cpp11 {
template<class... Ts>
constexpr auto copy_and_sum_ts(Ts&... ts){
return (0uz + ... + Ts(ts));
}
}
namespace cpp20 {
constexpr auto copy_and_sum_ts(auto&... ts){
return (0uz + ... + std::remove_cvref_t<decltype(ts)>(ts));
}
}
namespace cpp23 {
constexpr auto copy_and_sum_ts(auto&... ts){
return (0uz + ... + auto{ts});
}
}
namespace cpp20 {
constexpr auto copy_and_sum_ts(auto&... ts) {
return (0 + ... + [] (auto& t) { return t; }(ts));
}
}
namespace cpp23 {
constexpr auto copy_and_sum_ts(auto&... ts) {
return (0 + ... + auto{ts});
}
}
namespace cpp20 {
constexpr auto copy_and_sum_ts(auto&... ts) {
return (0 + ... + decltype(ts){ts});
}
} // namespace cpp20
namespace cpp23 {
constexpr auto copy_and_sum_ts(auto&... ts) { return (0 + ... + auto{ts}); }
} // namespace cpp23
namespace cpp20 {
constexpr auto copy_and_sum_ts(auto&... ts) {
return (std::remove_cvref_t<decltype(ts)>{ts} + ... + 0);
}
}
namespace cpp23 {
constexpr auto copy_and_sum_ts(auto&... ts) {
return (auto{ts} + ... + 0);
}
}
namespace cpp20 {
constexpr auto copy_and_sum_ts(auto&... ts){
return (decltype(ts){ts} + ... + 0);
}
}
namespace cpp23 {
constexpr auto copy_and_sum_ts(auto&... ts){
return (auto{ts} + ... + 0);
}
}
namespace cpp20 {
constexpr auto copy_and_sum_ts(auto&... ts) {
return (0 + ... + std::remove_cvref_t<decltype(ts)>{ts});
}
}
namespace cpp23 {
constexpr auto copy_and_sum_ts(auto&... ts) {
return (0 + ... + auto{ts});
}
}
namespace cpp20 {
constexpr auto copy_and_sum_ts(auto&... ts) {
constexpr auto Auto = [](auto x) {return x;};
return (0 + ... + Auto(ts));
}
}
namespace cpp23 {
constexpr auto copy_and_sum_ts(auto&... ts) { return (0 + ... + auto(ts)); }
}
template <class T>
typename std::decay<T>::type
constexpr decay_copy (T&& t) {
return std::forward<T>(t);
}
struct copy {
bool copied{};
constexpr copy() = default;
constexpr copy(const copy&) : copied{true} {}
constexpr operator auto() const { return copied; }
};
namespace cpp20 {
constexpr auto copy_and_sum_ts(auto&... ts){
return (decay_copy(ts) + ... + 0);
}
}
namespace cpp23 {
constexpr auto copy_and_sum_ts(auto&... ts){
return (auto(ts) + ... + 0);
}
}
namespace cpp20 {
constexpr auto copy_and_sum_ts(auto&... ts) {
return (copy(ts).copied + ... + 0);
}
}
namespace cpp23 {
constexpr auto copy_and_sum_ts(auto&... ts) {
return ( auto(ts).copied + ... + 0);
}
}