C++と色々

主にC++やプログラムに関する記事を投稿します。

ズンドコキヨシ with C++14

これ

qiita.com

なぜかC++版が無かったので。コードゴルフとかやらずに、ファンクタとイテレータで実装してみた。C++11では古くて動きません

#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>
#include <random>
#include <string>
#include <utility>

struct zundoko_generator {
    static const std::array<std::string, 2> zundoko;
    std::mt19937 engine{std::random_device{}()};
    std::uniform_int_distribution<> dist{0, 1};

    zundoko_generator() = default;
    zundoko_generator(zundoko_generator const&) = default;
    zundoko_generator& operator=(zundoko_generator const&) = default;
    zundoko_generator(zundoko_generator&&) = default;
    zundoko_generator& operator=(zundoko_generator&&) = default;
    ~zundoko_generator() noexcept = default;

    std::string operator()() {
        return zundoko[dist(engine)];
    }
};

const std::array<std::string, 2> zundoko_generator::zundoko{{"ズン", "ドコ"}};

class zundoko_iterator
    : public std::iterator<std::input_iterator_tag, std::string>
{
    std::array<std::string, 5> zundoko_buffer;
    zundoko_generator generator;
    value_type value{generator()};

    value_type update() {
        std::rotate(zundoko_buffer.begin(), std::next(zundoko_buffer.begin()), zundoko_buffer.end());
        zundoko_buffer.back() = value;
        return generator();
    }

public:
    zundoko_iterator() = default;
    zundoko_iterator(zundoko_iterator const&) = default;
    zundoko_iterator& operator=(zundoko_iterator const&) = default;
    zundoko_iterator(zundoko_iterator&&) = default;
    zundoko_iterator& operator=(zundoko_iterator&&) = default;
    ~zundoko_iterator() noexcept = default;

    bool operator==(zundoko_iterator const&) noexcept {
        std::array<std::string, 5> expect{{"ズン", "ズン", "ズン", "ズン", "ドコ"}};
        return std::equal(zundoko_buffer.begin(), zundoko_buffer.end(), expect.begin(), expect.end());
    }

    bool operator!=(zundoko_iterator const& that) noexcept {
        return !(*this == that);
    }

    value_type operator*() & {
        return value;
    }

    value_type operator*() && {
        return std::move(value);
    }

    pointer operator->() {
        return &value;
    }

    value_type operator++() {
        value = update();
        return value;
    }

    value_type operator++(int) {
        auto const before = value;
        value = update();
        return before;
    }

    void swap(zundoko_iterator& that) noexcept {
        using std::swap;
        swap(generator, that.generator);
        swap(value, that.value);
    }
};

int main() {
    std::copy(zundoko_iterator{}, zundoko_iterator{}, std::ostream_iterator<std::string>(std::cout, ""));
    std::cout << "キ・ヨ・シ!" << std::endl;
}

実行結果例 

[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ

MSVC14.0, clang++3.4以上, g++4.9.0以上で確認