Last active
August 29, 2015 14:01
-
-
Save miselin/fbe6b4e428b40ac3c305 to your computer and use it in GitHub Desktop.
clang++ -std=c++11 -o comma comma.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <list> | |
#include <vector> | |
#include <numeric> | |
#include <type_traits> | |
#include <typeinfo> | |
class _dumper { | |
public: | |
_dumper() : _dlist() {} | |
virtual ~_dumper() {} | |
virtual void basedump(std::ostream &os) const { | |
if (!_dlist.size()) { | |
dump(os, false); | |
} else { | |
_open(os); | |
for (auto it : _dlist) { | |
it->dump(os, true); | |
} | |
_close(os); | |
} | |
} | |
virtual void dump(std::ostream &os, bool siblings) const = 0; | |
protected: | |
void extend(const _dumper &other) { _dlist.push_back(&other); } | |
void _open(std::ostream &os) const { os << "( "; } | |
void _close(std::ostream &os) const { os << ") "; } | |
private: | |
std::list<const _dumper *> _dlist; | |
}; | |
template <typename T> class _basic_tuple : public _dumper { | |
public: | |
_basic_tuple() : _dumper(), _list() {} | |
virtual ~_basic_tuple() {} | |
_basic_tuple &operator, (T other) { | |
_list.push_back(other); | |
return const_cast<_basic_tuple &>(*this); | |
} | |
template <typename T2> _basic_tuple &operator, (_basic_tuple<T2> other) { | |
extend(*this); | |
extend(other); | |
return const_cast<_basic_tuple &>(*this); | |
} | |
operator size_t() { return _list.size(); } | |
T operator+() { | |
auto it = _list.begin(); | |
T r = *(it++); | |
for (; it != _list.end(); ++it) | |
r += *it; | |
return r; | |
} | |
T operator*() { | |
auto it = _list.begin(); | |
T r = *(it++); | |
for (; it != _list.end(); ++it) | |
r *= *it; | |
return r; | |
} | |
T operator-() { | |
auto it = _list.begin(); | |
T r = *(it++); | |
for (; it != _list.end(); ++it) | |
r -= *it; | |
return r; | |
} | |
virtual void dump(std::ostream &os = std::cout, bool siblings = false) const { | |
auto dumper_is_base = std::is_base_of<_dumper, T>(); | |
if (!siblings) | |
siblings = !dumper_is_base.value; | |
if (!siblings) | |
_open(os); | |
// The right overload must be emitted; it is not possible to simply call | |
// a different member function based on the result of std::is_base_of, | |
// as if an object of type T does not have a 'dump' function, the compiler | |
// errors out in template generation, eg: | |
// "member reference base type 'const char *' is not a structure or union" | |
do_dump(os, dumper_is_base); | |
if (!siblings) | |
_close(os); | |
} | |
private: | |
std::list<T> _list; | |
void do_dump(std::ostream &os, | |
std::true_type /* dummy for overload */) const { | |
for (auto it : _list) { | |
it.dump(os, true); | |
} | |
} | |
void do_dump(std::ostream &os, | |
std::false_type /* dummy for overload */) const { | |
_open(os); | |
for (auto it : _list) { | |
os << it << " "; | |
} | |
_close(os); | |
} | |
}; | |
class _tuple { | |
public: | |
template <typename T> _basic_tuple<T> operator, (T val) { | |
return _basic_tuple<T>(), val; | |
} | |
} _; | |
std::ostream &operator<<(std::ostream &os, const _dumper &val) { | |
val.basedump(os); | |
return os; | |
} | |
#define print(x...) \ | |
do { \ | |
_print((_, x)); \ | |
} while (0); | |
void _print(const _dumper &val) { std::cout << val << std::endl; } | |
int main(int argc, char *argv[]) { | |
(_, "hello", "world").dump(); | |
std::cout << std::endl; | |
size_t count = (_, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); | |
std::cout << count << std::endl; | |
std::cout << (_, 1, 2) << std::endl; | |
std::cout << (+(_, (*(_, 3, 2)), 1)) << std::endl; | |
std::cout << (-(_, 7, 4)) << std::endl; | |
std::cout << (+(_, std::string("hello"), " ", "world")) << std::endl; | |
std::cout << "====" << std::endl; | |
// Mixed types dump as you would expect. | |
std::cout << (_, (_, 3, 4), (_, 1, 2), (_, "hello world")) << std::endl; | |
std::cout << (_, (_, 3, 4), (_, 1, 2)) << std::endl; | |
print("Hello, world!") | |
print("Hello,", "world!") | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
( hello world ) | |
10 | |
( 1 2 ) | |
7 | |
3 | |
hello world | |
==== | |
( ( 3 4 ) ( 1 2 ) ( hello world ) ) | |
( ( 3 4 ) ( 1 2 ) ) | |
( Hello, world! ) | |
( Hello, world! ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment