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

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

定数マップ

昨日のエントリの続き。
ソート済み配列が手に入るとマップが作れます。ソートされていなくても線形検索すればいいんですが、それはそれ、効率よく検索したいじゃないですか。ソート済みなら二分探索ができるので、二分探索で実装した定数マップです。


以下コード。

// ConstMap.h

#ifndef CONSTMAP_H
#define CONSTMAP_H

#include "ConstSortedArray.h"

#include <stdexcept>

namespace emattsan
{

template<typename Key, typename T>
class ConstMap
{
public:
    typedef Key key_type;
    typedef T   mapped_type;

    struct Value
    {
        key_type    key;
        mapped_type value;

        bool operator < (const Value& other) const
        {
            return key < other.key;
        }
    };

    typedef Value value_type;


    template<int N>
    class Container
    {
    public:
        static const int size = N;

        explicit Container(const value_type (&array)[N]) : array_(array)
        {
        }

        const mapped_type& operator [] (const key_type& key) const
        {
            int left  = 0;
            int right = N;
            for(;;)
            {
                if(left >= right)
                {
                    throw std::out_of_range("not found");
                }

                int mid = (left + right) / 2;
                if(array_[mid].key == key)
                {
                    return array_[mid].value;
                }
                else if(array_[mid].key < key)
                {
                    left = mid + 1;
                }
                else
                {
                    right = mid;
                }
            }
        }

    private:
        const ConstSortedArray<value_type, N> array_;
    };
};

} // namespace emattsan

#endif//CONSTMAP_H


テスト。

#include "ConstMap.h"

#include <iostream>

namespace
{
template<typename T, int N>
char (&numberof_(T (&array)[N]))[N];
}

#define numberof(array) sizeof(numberof_(array))


typedef emattsan::ConstMap<int, const char*> SampleMap;

static const SampleMap::value_type items[] =
{
    { 1, "one"   },
    { 5, "five"  },
    { 8, "eight" },
    { 3, "three" },
    { 0, "zero"  },
    { 7, "seven" },
    { 4, "four"  },
    { 6, "six"   },
    { 2, "two"   },
    { 9, "nine"  }
};

int main(int, char* [])
{
    SampleMap::Container<numberof(items)> map(items);

    try
    {
        for(int i = 0; i < 11; ++i)
        {
            std::cout << map[i] << std::endl;
        }
    }
    catch(const std::exception& e)
    {
        std::cerr << "EXCEPTION THROWN : " << e.what() << std::endl;
    }

    return 0;
}