253 lines
9.1 KiB
C++
253 lines
9.1 KiB
C++
#include "generic_macros.h"
|
|
#include <fstream>
|
|
|
|
#ifndef ILYA_SHARED_HEADER_GENERIC
|
|
#define ILYA_SHARED_HEADER_GENERIC
|
|
|
|
namespace generic {
|
|
using namespace std;
|
|
|
|
|
|
template<class type_a> void print_impl(ostream& out, const type_a& a) {}
|
|
|
|
template<class type_b> void print_impl(ostream& out, const char* a, const type_b& b) {
|
|
out << " " << b;
|
|
}
|
|
|
|
template<class type_a, class type_b> void print_impl(ostream& out, const type_a& a, const type_b& b) {
|
|
out << ", " << b;
|
|
}
|
|
|
|
template<class type_a, class type_b, class... types> void print_impl(ostream& out, const type_a& a, const type_b& b, const types&... targs) {
|
|
print_impl(out, a, b);
|
|
print_impl(out, b, targs...);
|
|
}
|
|
|
|
template<class type_a, class... types> void print_to(ostream& out, const type_a& a, const types&... targs) {
|
|
out << a;
|
|
print_impl(out, a, targs...);
|
|
out << "\n";
|
|
}
|
|
|
|
template<class type_a, class... types> void print(const type_a& a, const types&... targs) {
|
|
print_to(cerr, a, targs...);
|
|
}
|
|
|
|
//if buffer is not null, will return an empty string
|
|
string getstream(istream& targ, int block_size=10, string* buffer=nullptr) {
|
|
string new_buffer;
|
|
string& res=(buffer!=nullptr)? *buffer : new_buffer;
|
|
res.clear();
|
|
|
|
while(1) {
|
|
res.resize(res.size()+block_size);
|
|
targ.read(&(res[res.size()-block_size]), block_size);
|
|
int c=targ.gcount();
|
|
if (c!=block_size) {
|
|
res.resize(res.size()-block_size+c);
|
|
assert(targ.eof());
|
|
return new_buffer;
|
|
}
|
|
}
|
|
}
|
|
|
|
string getfile(const string& name, bool binary=0, int block_size=1024) {
|
|
ifstream in(name, binary? ios::binary|ios_base::in : ios_base::in);
|
|
assert(in.good());
|
|
return getstream(in, block_size);
|
|
}
|
|
|
|
struct less_ptr {
|
|
template<class ptr_type> bool operator()(ptr_type a, ptr_type b) {
|
|
return *a<*b;
|
|
}
|
|
};
|
|
|
|
template<class type> type instance_of();
|
|
|
|
template<class type> std::string to_string(std::ostringstream& s, const type& targ) {
|
|
s.clear();
|
|
s.str("");
|
|
s << targ;
|
|
return s.str();
|
|
}
|
|
template<class type> std::string to_string(const type& targ) {
|
|
static std::ostringstream s;
|
|
return to_string(s, targ);
|
|
}
|
|
|
|
template<class type> pair<type, bool> checked_from_string(std::istringstream& s, const std::string& targ) {
|
|
s.clear();
|
|
s.str(targ);
|
|
type res;
|
|
s >> res;
|
|
return make_pair(res, s.eof() && !s.fail());
|
|
}
|
|
template<class type> type from_string(std::istringstream& s, const std::string& targ) {
|
|
return checked_from_string<type>(s, targ).first;
|
|
}
|
|
template<class type> type from_string(const std::string& targ) {
|
|
static std::istringstream s;
|
|
return from_string<type>(s, targ);
|
|
}
|
|
template<class type> pair<type, bool> checked_from_string(const std::string& targ) {
|
|
static std::istringstream s;
|
|
return checked_from_string<type>(s, targ);
|
|
}
|
|
|
|
template<class type> type assert_from_string(const std::string& targ) {
|
|
auto res=checked_from_string<type>(targ);
|
|
assert(res.second);
|
|
return res.first;
|
|
}
|
|
|
|
template<class type, class... types> unique_ptr<type> make_unique_ptr(types&&... targs) {
|
|
return unique_ptr<type>(new type(forward<types>(targs)...));
|
|
}
|
|
|
|
template<class type, int size> int array_size(type(&)[size]) {
|
|
return size;
|
|
}
|
|
|
|
template<class type> std::ostream& print_as_number(std::ostream& out, const type& targ) { out << targ; return out; }
|
|
template<> std::ostream& print_as_number<unsigned char>(std::ostream& out, const unsigned char& targ) { out << int(targ); return out; }
|
|
template<> std::ostream& print_as_number<signed char>(std::ostream& out, const signed char& targ) { out << int(targ); return out; }
|
|
template<> std::ostream& print_as_number<char>(std::ostream& out, const char& targ) { out << int(targ); return out; }
|
|
|
|
//
|
|
|
|
template<bool n, class type> struct only_if {};
|
|
template<class type> struct only_if<1, type> { typedef type good; };
|
|
template<bool n> typename only_if<n, void>::good assert_true() {}
|
|
|
|
template<class a, class b, class type> struct only_if_same_types {};
|
|
template<class a, class type> struct only_if_same_types<a, a, type> { typedef type good; };
|
|
template<class a, class b> typename only_if_same_types<a, b, void>::good assert_same_types() {}
|
|
|
|
template<class a, class b, class type> struct only_if_not_same_types { typedef type good; };
|
|
template<class a, class type> struct only_if_not_same_types<a, a, type> {};
|
|
template<class a, class b> typename only_if_not_same_types<a, b, void>::good assert_not_same_types() {}
|
|
|
|
template<int n> struct static_abs { static const int res=n<0? -n : n; };
|
|
template<int n> struct static_sgn { static const int res=n<0? -1 : (n>0? 1 : 0); };
|
|
template<int a, int b> struct static_max { static const int res=a>b? a : b; };
|
|
template<int a, int b> struct static_min { static const int res=a<b? a : b; };
|
|
|
|
template<class type> class wrap_type { typedef type res; };
|
|
|
|
//
|
|
|
|
template<class type_a, class type_b> class union_pair {
|
|
template<class, class> friend class union_pair;
|
|
static const size_t size_bytes=static_max<sizeof(type_a), sizeof(type_b)>::res;
|
|
static const size_t alignment_bytes=static_max<alignof(type_a), alignof(type_b)>::res;
|
|
typename aligned_storage<size_bytes, alignment_bytes>::type buffer;
|
|
bool t_is_first;
|
|
|
|
public:
|
|
union_pair() : t_is_first(1) { new(&buffer) type_a(); }
|
|
union_pair(int, int) : t_is_first(0) { new(&buffer) type_b(); }
|
|
union_pair(const type_a& targ) : t_is_first(1) { new(&buffer) type_a(targ); }
|
|
union_pair(const type_b& targ) : t_is_first(0) { new(&buffer) type_b(targ); }
|
|
union_pair(type_a&& targ) : t_is_first(1) { new(&buffer) type_a(move(targ)); }
|
|
union_pair(type_b&& targ) : t_is_first(0) { new(&buffer) type_b(move(targ)); }
|
|
union_pair(const union_pair& targ) : t_is_first(targ.t_is_first) {
|
|
if (t_is_first) new(&buffer) type_a(targ.first()); else new(&buffer) type_b(targ.second());
|
|
}
|
|
union_pair(const union_pair<type_b, type_a>& targ) : t_is_first(!targ.t_is_first) {
|
|
if (t_is_first) new(&buffer) type_a(targ.second()); else new(&buffer) type_b(targ.first());
|
|
}
|
|
union_pair(union_pair&& targ) : t_is_first(targ.t_is_first) {
|
|
if (t_is_first) new(&buffer) type_a(move(targ.first())); else new(&buffer) type_b(move(targ.second()));
|
|
}
|
|
union_pair(union_pair<type_b, type_a>&& targ) : t_is_first(!targ.t_is_first) {
|
|
if (t_is_first) new(&buffer) type_a(move(targ.second())); else new(&buffer) type_b(move(targ.first()));
|
|
}
|
|
|
|
union_pair& operator=(const type_a& targ) {
|
|
if (is_first()) first()=targ; else set_first(targ);
|
|
return *this;
|
|
}
|
|
union_pair& operator=(const type_b& targ) {
|
|
if (is_second()) second()=targ; else set_second(targ);
|
|
return *this;
|
|
}
|
|
|
|
union_pair& operator=(type_a&& targ) {
|
|
if (is_first()) first()=move(targ); else set_first(move(targ));
|
|
return *this;
|
|
}
|
|
union_pair& operator=(type_b&& targ) {
|
|
if (is_second()) second()=move(targ); else set_second(move(targ));
|
|
return *this;
|
|
}
|
|
|
|
union_pair& operator=(const union_pair& targ) {
|
|
if (targ.is_first()) {
|
|
return *this=targ.first();
|
|
} else {
|
|
return *this=targ.second();
|
|
}
|
|
}
|
|
union_pair& operator=(const union_pair<type_b, type_a>& targ) {
|
|
if (targ.is_first()) {
|
|
return *this=targ.first();
|
|
} else {
|
|
return *this=targ.second();
|
|
}
|
|
}
|
|
|
|
union_pair& operator=(union_pair&& targ) {
|
|
if (targ.is_first()) {
|
|
return *this=move(targ.first());
|
|
} else {
|
|
return *this=move(targ.second());
|
|
}
|
|
}
|
|
union_pair& operator=(union_pair<type_b, type_a>&& targ) {
|
|
if (targ.is_first()) {
|
|
return *this=move(targ.first());
|
|
} else {
|
|
return *this=move(targ.second());
|
|
}
|
|
}
|
|
|
|
typedef type_a first_type;
|
|
typedef type_b second_type;
|
|
|
|
bool is_first() const { return t_is_first; }
|
|
bool is_second() const { return !t_is_first; }
|
|
//
|
|
type_a& first() { return *reinterpret_cast<type_a*>(&buffer); }
|
|
const type_a& first() const { return *reinterpret_cast<const type_a*>(&buffer); }
|
|
type_b& second() { return *reinterpret_cast<type_b*>(&buffer); }
|
|
const type_b& second() const { return *reinterpret_cast<const type_b*>(&buffer); }
|
|
//
|
|
template<class... types> type_a& set_first(types&&... targs) {
|
|
if (!t_is_first) {
|
|
second().~type_b();
|
|
t_is_first=1;
|
|
} else {
|
|
first().~type_a();
|
|
}
|
|
return *(new(&buffer) type_a(forward<types>(targs)...));
|
|
}
|
|
template<class... types> type_b& set_second(types&&... targs) {
|
|
if (t_is_first) {
|
|
first().~type_a();
|
|
t_is_first=0;
|
|
} else {
|
|
second().~type_b();
|
|
}
|
|
return *(new(&buffer) type_b(forward<types>(targs)...));
|
|
}
|
|
|
|
~union_pair() {
|
|
if (t_is_first) first().~type_a(); else second().~type_b();
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|