エンジニアのソフトウェア的愛情

または私は如何にして心配するのを止めてプログラムを・愛する・ようになったか

スマート列挙型その4

なんか…ライフワークのようになっている賢い列挙型の追求。

operator <=と見立てて。
とりあえず9個まで対応。

#include <iostream>

template<typename T, int N>
class Set
{
public:
    Set(T a1, T a2) : value_(a1), set_(a2) {}
    Set(T a1, T a2, T a3) : value_(a1), set_(a2, a3) {}
    Set(T a1, T a2, T a3, T a4) : value_(a1), set_(a2, a3, a4) {}
    Set(T a1, T a2, T a3, T a4, T a5) : value_(a1), set_(a2, a3, a4, a5) {}
    Set(T a1, T a2, T a3, T a4, T a5, T a6) : value_(a1), set_(a2, a3, a4, a5, a6) {}
    Set(T a1, T a2, T a3, T a4, T a5, T a6, T a7) : value_(a1), set_(a2, a3, a4, a5, a6, a7) {}
    Set(T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8) : value_(a1), set_(a2, a3, a4, a5, a6, a7, a8) {}
    Set(T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8, T a9) : value_(a1), set_(a2, a3, a4, a5, a6, a7, a8, a9) {}

    bool includes(T value) const { return (value == value_) || set_.includes(value); }

private:
    const T           value_;
    const Set<T, N-1> set_;
};

template<typename T>
class Set<T, 1>
{
public:
    Set(T a1) : value_(a1) {}

    bool includes(T value) const { return (value == value_); }

private:
    T value_;
};

template<typename T, int N>
bool operator <= (T value, const Set<T, N>& set) { return set.includes(value); }

template<typename T> Set<T, 1> setOf(T a1) { return Set<T, 1>(a1); }
template<typename T> Set<T, 2> setOf(T a1, T a2) { return Set<T, 2>(a1, a2); }
template<typename T> Set<T, 3> setOf(T a1, T a2, T a3) { return Set<T, 3>(a1, a2, a3); }
template<typename T> Set<T, 4> setOf(T a1, T a2, T a3, T a4) { return Set<T, 4>(a1, a2, a3, a4); }
template<typename T> Set<T, 5> setOf(T a1, T a2, T a3, T a4, T a5) { return Set<T, 5>(a1, a2, a3, a4, a5); }
template<typename T> Set<T, 6> setOf(T a1, T a2, T a3, T a4, T a5, T a6) { return Set<T, 6>(a1, a2, a3, a4, a5, a6); }
template<typename T> Set<T, 7> setOf(T a1, T a2, T a3, T a4, T a5, T a6, T a7) { return Set<T, 7>(a1, a2, a3, a4, a5, a6, a7); }
template<typename T> Set<T, 8> setOf(T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8) { return Set<T, 8>(a1, a2, a3, a4, a5, a6, a7, a8); }
template<typename T> Set<T, 9> setOf(T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8, T a9) { return Set<T, 9>(a1, a2, a3, a4, a5, a6, a7, a8, a9); }

enum Kanto { Chiba, Gunma, Ibaraki, Kanagawa, 
                       Saitama, Tochigi, Tokyo };

void hantei(Kanto k)
{
    if(k <= setOf(Gunma, Ibaraki, Tochigi))
    {
        std::cout << "北関東" << std::endl;
    }
    else if(k <= setOf(Chiba, Kanagawa, Saitama, Tokyo))
    {
        std::cout << "南関東" << std::endl;
    }
    else
    {
        std::cout << "どこだ?" << std::endl;
    }
}

こういう場合、多態をつかって解決するのが正当なのだろうということに、書き上げてから気がついた。