73 lines
1.9 KiB
C++
73 lines
1.9 KiB
C++
#include <cassert>
|
|
#include <sstream>
|
|
#include <string>
|
|
|
|
using namespace std::string_literals;
|
|
|
|
template <typename T> auto sum(T final) { return final; }
|
|
template <typename T, typename... Ts> auto sum(T first, Ts... rem) {
|
|
return first + sum<Ts...>(rem...);
|
|
}
|
|
|
|
class ss_sum {
|
|
std::stringstream ss;
|
|
|
|
public:
|
|
template <typename T> ss_sum(T obj) : ss{} { ss << obj; }
|
|
ss_sum(ss_sum const &rhs) : ss{} {
|
|
std::string tmp;
|
|
const_cast<ss_sum &>(rhs).ss >> tmp;
|
|
const_cast<ss_sum &>(rhs).ss << tmp;
|
|
ss << tmp;
|
|
}
|
|
ss_sum &operator=(ss_sum const &rhs) {
|
|
std::string tmp;
|
|
// clear out string stream
|
|
ss >> tmp;
|
|
|
|
const_cast<ss_sum &>(rhs).ss >> tmp;
|
|
const_cast<ss_sum &>(rhs).ss << tmp;
|
|
ss << tmp;
|
|
return *this;
|
|
}
|
|
friend ss_sum operator+(ss_sum const &lhs, ss_sum const &rhs) {
|
|
ss_sum ret = lhs;
|
|
ss_sum tmp = rhs;
|
|
std::string a;
|
|
tmp.ss >> a;
|
|
ret.ss << a;
|
|
return ret;
|
|
}
|
|
friend bool operator==(ss_sum const &lhs, ss_sum const &rhs) {
|
|
ss_sum inner_l = lhs;
|
|
ss_sum inner_r = rhs;
|
|
std::string l;
|
|
std::string r;
|
|
inner_l.ss >> l;
|
|
inner_r.ss >> r;
|
|
return l == r;
|
|
}
|
|
};
|
|
|
|
int main(void) {
|
|
bool dummy = sum<double, int, int, int>(1.5, 2, 3, 10) == 16.5;
|
|
assert(dummy);
|
|
dummy = sum<int, int, int, int, int, int, int>(1, 5, 7, 8, 2, 3, 4) == 30;
|
|
assert(dummy);
|
|
dummy = sum<double>(1.5, 1, 2, 3.5) == 8.0;
|
|
assert(dummy);
|
|
dummy = sum<std::string>("asdf"s, "abcdefghijklmnop"s, "qrstuvwxyz"s) ==
|
|
"asdfabcdefghijklmnopqrstuvwxyz"s;
|
|
assert(dummy);
|
|
|
|
// ss_sum is only associative when everything is ss_sum
|
|
auto tmp = sum<ss_sum, ss_sum, ss_sum>(1, 2, 3);
|
|
dummy = tmp == ss_sum{"123"};
|
|
assert(dummy);
|
|
|
|
// demo of situation where associativity isn't applicable ss_sum+(int+int) !=
|
|
// (ss_sum+int)+int
|
|
tmp = sum<ss_sum, int, int>(1, 2, 3);
|
|
dummy = tmp == ss_sum{"15"};
|
|
assert(dummy);
|
|
}
|