182.md
September 9, 2022 ยท View on GitHub
Info
- Did you know about the proposal to add Non-terminal variadic template parameters?
Example
template<class... Ts, class T>
auto foo(Ts..., T t) { return t; }
int main() {
std::cout << foo(1); // prints 1
std::cout << foo(1, 2, 3, 4); // prints 4
std::cout << foo(); // compilation error
}
Puzzle
- [NTVTP] Can you implement
last_using_{get,apply,inplace_lambda}functions which will return the last element of given tuple?
/* TODO */
constexpr auto last_using_get(...);
constexpr auto last_using_apply(...);
constexpr auto last_using_inplace_lambda(...);
int main() {
"tuple - get last"_test = [] {
should("return the only element") = []{
auto tuple = std::tuple{42};
42_i == last_using_get(tuple) and
42_i == last_using_apply(tuple) and
42_i == last_using_inplace_lambda(tuple);
};
should("return the last element with same types") = [] {
auto tuple = std::tuple{4l, 2l, 42l};
42_l == last_using_get(tuple) and
42_l == last_using_apply(tuple) and
42_l == last_using_inplace_lambda(tuple);
};
should("return the last element with differen types") = [] {
auto tuple = std::tuple{1, 2.0, "3", 4ul};
4_ul == last_using_get(tuple) and
4_ul == last_using_apply(tuple) and
4_ul == last_using_inplace_lambda(tuple);
};
};
}
Solutions
constexpr auto last_using_get(const auto& tuple) noexcept
{
using tuple_type = std::decay_t<decltype(tuple)>;
return std::get<std::tuple_size_v<tuple_type> - 1>(tuple);
}
constexpr auto last_using_apply(const auto& tuple)
{
return std::apply([](const auto... args) { return (args, ...); }, tuple);
}
constexpr auto last_using_inplace_lambda(const auto& tuple) {
return [&](){
return last_using_get(tuple);
}();
}
template <typename TTuple>
constexpr auto last_using_get(TTuple&& t) -> decltype(auto) {
constexpr auto size = std::tuple_size_v<std::remove_reference_t<TTuple>>;
return std::get<size-1>(std::forward<TTuple>(t));
}
template <typename TTuple>
constexpr auto last_using_apply(TTuple&& t) -> decltype(auto) {
return std::apply(
[](auto&&...args) -> decltype(auto) {
return (std::forward<decltype(args)>(args), ...);
},
std::forward<TTuple>(t));
}
template <typename TTuple>
constexpr auto last_using_inplace_lambda(TTuple&& t) -> decltype(auto) {
constexpr auto size = std::tuple_size_v<std::remove_reference_t<TTuple>>;
return [&] <auto... I> (std::index_sequence<I...>) -> decltype(auto) {
return std::get<(I,...)>(std::forward<TTuple>(t));
}(std::make_index_sequence<size>{});
}