Boost.Move に対応した array

※ Boost.Move の入っている revision について書きます
Boost.Interprocess には Boost.Move に対応したコンテナが付属していますが、その中に std::array に相当するものはありません。これは、move constructor などを追加することにより、array が aggregate でなくなってしまうためだと思われます。しかし、そこを強引に解決したくなるのが人情というものです (訳: 暇だった)。
https://gist.github.com/956977
短いコードですが少しだけ解説を加えます。
データの表現方法ですが、配列は使えません。コンストラクタの先頭で必ず value-initialize されるためです。そこで、アラインメントされた生のストレージを用います。

    typename boost::aligned_storage<
        sizeof(T) * (N ? N : 1), boost::alignment_of<T>::value>::type members;

    // access:
    pointer data()
    { return static_cast<pointer>(members.address()); }

    const_pointer data() const
    { return static_cast<const_pointer>(members.address()); }

Move constructor と move assignment operator の実装は次のようになります。

    array(BOOST_RV_REF(array) x)
    { boost::uninitialized_move(x.begin(), x.end(), data()); }

    array &operator=(BOOST_RV_REF(array) x)
    { boost::move(x.begin(), x.end(), begin()); return *this; }

さらに、aggregate として初期化できなくなった分を補わなくてはならないので、Boost.PP を使って複数コンストラクタを用意します。

    array()
    {
        size_type i = 0;
        try {
            for (; i < N; ++i) new(data() + i) T();
        }
        catch (...) {
            for (; i > 0; --i) data()[i - 1].~T();
            throw;
        }
    }

#define BOOST_PP_LOCAL_MACRO(n) \
    template <BOOST_PP_ENUM_PARAMS(n, class A)> \
    array(BOOST_PP_ENUM(n, RETRO_ARRAY_CONSTRUCTOR_ARGS, ~)) \
    { \
        BOOST_STATIC_ASSERT(n <= N); \
        size_type i = 0; \
        try { \
            BOOST_PP_REPEAT(n, RETRO_ARRAY_CONSTRUCTOR_FORWARD, ~) \
            for (; i < N; ++i) new(data() + i) T(); \
        } \
        catch (...) { \
            for (; i > 0; --i) data()[i - 1].~T(); \
            throw; \
        } \
    } \
    /**/
#define RETRO_ARRAY_CONSTRUCTOR_ARGS(z, m, unused) \
    BOOST_FWD_REF(BOOST_PP_CAT(A, m)) BOOST_PP_CAT(a, m) \
    /**/
#define RETRO_ARRAY_CONSTRUCTOR_FORWARD(z, m, unused) \
    new(data() + m) T(boost::forward<BOOST_PP_CAT(A, m)>(BOOST_PP_CAT(a, m))); \
    ++i; \
    /**/
#define BOOST_PP_LOCAL_LIMITS (1, RETRO_ARRAY_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#undef RETRO_ARRAY_CONSTRUCTOR_FORWARD
#undef RETRO_ARRAY_CONSTRUCTOR_ARGS

引数を BOOST_FWD_REF で受けているので、その制限が伴います。しかし、多くの場合には問題ないでしょう。
ではサンプルコードを示します。

#include <iostream>
#include <boost/interprocess/containers/string.hpp>
#include <boost/foreach.hpp>
#include "./array.hpp"

int main()
{
    using boost::interprocess::string;

    retro::array<string, 5> a1("Hello", ", ", "world", "!");
    // the 5th element is value-initialized

    retro::array<string, 5> const a2(boost::move(a1));

    std::cout << "a1: ";
    BOOST_FOREACH(string const &s, a1) std::cout << s; // (nothing displayed)

    std::cout << "\na2: ";
    BOOST_FOREACH(string const &s, a2) std::cout << s; // Hello, world!
}

依然として array a = {{{0, 0}, {1, 2}}}; のようなコードは書けませんが、そこは妥協しましょう。