Squeakers's blog

By Squeakers, history, 3 years ago, In English

I have put together a few functions that might be helpful to others. I didn't thoroughly test it. as I no longer do competitive programming. so please try it and let me know.

C++17 compiler is required.

Compiler Explorer link https://godbolt.org/z/M16vrTheh

#include <algorithm>
#include <array>
#include <assert.h>
#include <iostream>
#include <numeric>
#include <tuple>
#include <type_traits>
#include <vector>

using namespace std;

// clang-format off
template <typename T, typename = void> struct is_container : std::false_type {}; 
template <typename T> constexpr const char* type_to_format() { if constexpr (std::is_same_v<T, int>) return "%d"; else if constexpr (std::is_same_v<T, float>) return "%f"; else if constexpr(std::is_same_v<T, char>) return "%c"; else if constexpr(std::is_same_v<T, double>) return "%lf"; else if constexpr(std::is_same_v<T, unsigned int>) return "%u"; else if constexpr(std::is_same_v<T, short int>) return "%hd"; else if constexpr(std::is_same_v<T, long int>) return "%li"; else if constexpr(std::is_same_v<T, long long int>) return "%lli"; else if constexpr(std::is_same_v<T, unsigned long int>) return "%lu"; else if constexpr(std::is_same_v<T, unsigned long long int>) return "%llu"; else if constexpr(std::is_same_v<T, signed char>) return "%c"; else if constexpr(std::is_same_v<T, unsigned char>) return "%c"; else if constexpr(std::is_same_v<T, long double>) return "%Lf"; else return ""; }
template <typename T> struct is_container<T, std::void_t<decltype(std::declval<T>().begin()), decltype(std::declval<T>().end()), typename T::value_type>> : std::true_type { };
#define d_print(arg) println(#arg, "=", arg) 
template <typename... Args> void print(Args&&... args) { auto _print = [](auto&& arg, bool print_space = false) { if (print_space) std::cout << ' '; if constexpr(std::is_convertible_v<typename std::decay<decltype(arg)>::type, std::string>) { std::cout<< arg; } else if constexpr (is_container<typename std::decay<decltype(arg)>::type>::value || std::is_array_v<typename std::remove_reference<decltype(arg)>::type>) { size_t i = 0, sz = std::size(arg); if (!sz) { std::cout << "[]"; return; } for (std::cout << "[ "; i < sz; i++) { print(arg[i]); print(' '); } std::cout << "]"; } else { std::cout << arg; } }; [&_print](auto&& first, auto&&... rest) { _print(std::forward<decltype(first)>(first)); if constexpr (sizeof...(rest) > 0) ((_print(std::forward<decltype(rest)>(rest), true)), ...); }(std::forward<decltype(args)>(args)...); }
template <typename... Args> void println(Args &&... args) { print(std::forward<Args>(args)..., '\n'); }
template <typename T, typename F, std::size_t... I> constexpr void visit_impl(T& tup, const size_t idx, F fun, std::index_sequence<I...>) { assert(idx < std::tuple_size_v<T>); ((I == idx ? fun(std::get<I>(tup)) : void()), ...); }
template <typename F, typename... Ts, typename Indices = std::make_index_sequence<sizeof...(Ts)>> constexpr void visit_at(std::tuple<Ts...>& tup, const size_t idx, F fun) { visit_impl(tup, idx, fun, Indices{}); }
template <typename F, typename... Ts, typename Indices = std::make_index_sequence<sizeof...(Ts)>> constexpr void visit_at(const std::tuple<Ts...>& tup, const size_t idx, F fun) { visit_impl(tup, idx, fun, Indices{}); }
template <typename... Args> void input(Args&... args) { ( [](auto&& arg) { if constexpr (std::is_same_v<typename std::decay<decltype(arg)>::type, std::string>) std::cin >> arg; else if constexpr (is_container<typename std::decay<decltype(arg)>::type>::value == true || std::is_array_v<typename std::remove_reference<decltype(arg)>::type>) { for (size_t i = 0, sz = std::size(arg); i < sz; i++) { input(arg[i]); } } else scanf(type_to_format<typename std::decay<decltype(arg)>::type>(), &arg); }(std::forward<Args>(args)), ...); }
template<typename T> T input() { T t; input(t); return t; }
template<typename A, typename B, typename ...Args> decltype(auto) input() { std::tuple<A, B, Args...> out{}; for (size_t i = 0; i < sizeof...(Args) + 2; i++) { visit_at(out, i , [](auto&& arg) { input(arg); }); } return out; }
// clang-format on

int main()
{

    println("Look", string("at"), " these nice numbers", 1, 2.f, 3.3,
            array<int, 3>{ 3, 3, 3 }, vector<int>{ 5, 6, 9 },
            array<array<int,2>, 2> {{{2,2},{4,4}}}
        );
    //
    // Example 1
    auto t = input<int>();
    println(t);
    while (t--)
    {
        int n;
        input(n);
        println(n);
    }

    // Example 2
    // returns a tuple. using structured binding to unpack
    auto [a, b, c] = input<int, int, float>();
    println(a, b, c);
    int aa, bb, cc;
    input(aa, bb, cc);
    println(aa, bb, cc);

    // Example 3

    auto n = input<int>();
    auto v = std::vector<float>(n);
    input(v);
    println(v);

    // example 4
    int arr[5];
    input(arr);
    print(arr, "nice");
}

Full text and comments »

  • Vote: I like it
  • +3
  • Vote: I do not like it