Skip to content

Instantly share code, notes, and snippets.

@macrat
Last active May 23, 2016 12:40
Show Gist options
  • Save macrat/47d424e3401a236a6c509d3a0bc3c2b8 to your computer and use it in GitHub Desktop.
Save macrat/47d424e3401a236a6c509d3a0bc3c2b8 to your computer and use it in GitHub Desktop.
FQDNで安全なFizzBuzzライフ。
#include <iostream>
#include <iterator>
#include <memory>
namespace funnycounter {
namespace item {
namespace interface {
class Stringer {
public:
virtual operator std::string() const = 0;
};
std::ostream& operator <<(std::ostream& os, funnycounter::item::interface::Stringer& x){
return os << (std::string)x;
}
std::ostream& operator <<(std::ostream& os, std::shared_ptr<funnycounter::item::interface::Stringer> x){
return os << *x;
}
}
namespace templatebase {
template <class T> class Item : public funnycounter::item::interface::Stringer {
protected:
T value;
public:
Item(T value){
this->value = value;
}
virtual operator std::string() const override;
template <class U> funnycounter::item::templatebase::Item<std::string> operator +(const funnycounter::item::templatebase::Item<U>& i) const {
return funnycounter::item::templatebase::Item<std::string>((std::string)*this + (std::string)i);
}
funnycounter::item::templatebase::Item<std::string> operator *(const int n) const {
std::string r;
for(int i=0; i<n; i++){
r += (std::string)*this;
}
return funnycounter::item::templatebase::Item<std::string>(r);
}
template <class U> std::shared_ptr<funnycounter::item::interface::Stringer> operator ||(const funnycounter::item::templatebase::Item<U>& i) const {
if(((std::string)*this).length()){
return std::shared_ptr<funnycounter::item::interface::Stringer>(new funnycounter::item::templatebase::Item<T>(this->value));
}else{
return std::shared_ptr<funnycounter::item::interface::Stringer>(new funnycounter::item::templatebase::Item<U>(i));
}
}
};
template <class T> funnycounter::item::templatebase::Item<T>::operator std::string() const {
return std::to_string(this->value);
}
template < > funnycounter::item::templatebase::Item<std::string>::operator std::string() const {
return this->value;
}
}
}
namespace counter {
template <class Converter, class ItemType> class Counter {
private:
int s, e;
public:
class Iterator : public std::iterator<std::input_iterator_tag, ItemType, void> {
private:
int itr;
public:
Iterator(const int pos){
this->itr = pos;
}
std::shared_ptr<funnycounter::item::interface::Stringer> operator *() const {
return Converter::convert(this->itr);
}
funnycounter::counter::Counter<Converter, ItemType>::Iterator& operator ++(){
this->itr++;
return *this;
}
const bool operator !=(const funnycounter::counter::Counter<Converter, ItemType>::Iterator& x) const {
return this->itr != x.itr;
}
};
Counter(const int start, const int end){
this->s = start;
this->e = end;
}
Counter(const int end) : funnycounter::counter::Counter<Converter, ItemType>::Counter(1, end) { }
funnycounter::counter::Counter<Converter, ItemType>::Iterator begin() const {
return funnycounter::counter::Counter<Converter, ItemType>::Iterator(this->s);
}
funnycounter::counter::Counter<Converter, ItemType>::Iterator end() const {
return funnycounter::counter::Counter<Converter, ItemType>::Iterator(this->e);
}
};
}
namespace fizzbuzz {
class Converter {
public:
static std::shared_ptr<funnycounter::item::interface::Stringer> convert(const int n) {
auto check = [n](int y) -> bool { int x = n; while(x >= y) x -= y; return !x; };
return std::shared_ptr<funnycounter::item::interface::Stringer>(funnycounter::item::templatebase::Item<std::string>("Fizz") * check(3) + funnycounter::item::templatebase::Item<std::string>("Buzz") * check(5) || funnycounter::item::templatebase::Item<int>(n));
}
};
}
}
int main(){
for(funnycounter::counter::Counter<funnycounter::fizzbuzz::Converter, funnycounter::item::interface::Stringer>::Iterator itr = funnycounter::counter::Counter<funnycounter::fizzbuzz::Converter, funnycounter::item::interface::Stringer>(20).begin(); itr != funnycounter::counter::Counter<funnycounter::fizzbuzz::Converter, funnycounter::item::interface::Stringer>(20).end(); ++itr){
std::cout << *itr << std::endl;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment