LINUX.ORG.RU

История изменений

Исправление quasimoto, (текущая версия) :

Ещё слегка поправленный вариант для тех же статических std::array:

#include <array>
#include <functional>
#include <iostream>

#include <boost/optional/optional.hpp>

template<size_t n> struct fin_s;
template<> struct fin_s<1> { enum enum_type : size_t { _0 }; };
template<> struct fin_s<2> { enum enum_type : size_t { _0, _1 }; };
template<> struct fin_s<3> { enum enum_type : size_t { _0, _1, _2 }; };
// ...

template <size_t n> using fin = typename fin_s<n>::enum_type;

template<size_t n, typename T>
T get(std::array<T, n> const& xs, fin<n> i)
{
    return xs[static_cast<size_t>(i)];
}

template <size_t n>
boost::optional<fin<n>> to_fin(size_t i)
{
    return i < n ? boost::optional<fin<n>>(static_cast<fin<n>>(i)) : boost::optional<fin<n>>();
}

// `optional' eliminator
template <typename A, typename T>
A choose(boost::optional<T> const& x, std::function<A()> f, std::function<A(T)> g)
{
    return x ? g(*x) : f();
}

int main()
{
    std::array<int, 3> xs = {{ 1, 2, 3 }};

    std::cout << "last is " << get(xs, fin<3>::_2) << std::endl;

    size_t i {};
    std::cin >> i;

    choose<void, fin<3>>(
        to_fin<3>(i),
        []() { std::cout << "bad index" << std::endl; },
        [&](fin<3> ix) {
            std::cout << "it is " << get(xs, ix) << std::endl;
        }
    );

}

Исправление quasimoto, :

Ещё слегка поправленный вариант для тех же статических std::array:

#include <array>
#include <functional>
#include <iostream>

#include <boost/optional/optional.hpp>

template<size_t n> struct fin_s;
template<> struct fin_s<1> { enum enum_type : size_t { _0 }; };
template<> struct fin_s<2> { enum enum_type : size_t { _0, _1 }; };
template<> struct fin_s<3> { enum enum_type : size_t { _0, _1, _2 }; };
// ...

template <size_t n> using fin = typename fin_s<n>::enum_type;

template<size_t n, typename T>
T get(std::array<T, n> xs, fin<n> i)
{
    return xs[static_cast<size_t>(i)];
}

template <size_t n>
boost::optional<fin<n>> to_fin(size_t i)
{
    return i < n ? boost::optional<fin<n>>(static_cast<fin<n>>(i)) : boost::optional<fin<n>>();
}

// `optional' eliminator
template <typename A, typename T>
A choose(boost::optional<T> const &x, std::function<A()> f, std::function<A(T)> g)
{
    return x ? g(*x) : f();
}

int main()
{
    std::array<int, 3> xs = {{ 1, 2, 3 }};

    std::cout << "last is " << get(xs, fin<3>::_2) << std::endl;

    size_t i {};
    std::cin >> i;

    choose<void, fin<3>>(
        to_fin<3>(i),
        []() { std::cout << "bad index" << std::endl; },
        [&](fin<3> ix) {
            std::cout << "it is " << get(xs, ix) << std::endl;
        }
    );

}

Исходная версия quasimoto, :

Ещё слегка поправленный вариант для тех же статических std::array:

#include <array>
#include <functional>
#include <iostream>

#include <boost/optional/optional.hpp>

template<size_t n> struct fin_s;
template<> struct fin_s<1> { enum enum_type : size_t { _0 }; };
template<> struct fin_s<2> { enum enum_type : size_t { _0, _1 }; };
template<> struct fin_s<3> { enum enum_type : size_t { _0, _1, _2 }; };
// ...

template <size_t n> using fin = typename fin_s<n>::enum_type;

template<size_t n, typename T>
T get(std::array<T, n> xs, fin<n> i)
{
    return xs[static_cast<size_t>(i)];
}

template <size_t n>
boost::optional<fin<n>> to_fin(size_t i)
{
    return i < n ? boost::optional<fin<n>>(static_cast<fin<n>>(i)) : boost::optional<fin<n>>();
}

// `optional' eliminator
template <typename A, typename T>
A choose(boost::optional<T> const &x, std::function<A()> f, std::function<A(T)> g) {
    return x ? g(*x) : f();
}

int main()
{
    std::array<int, 3> xs = {{ 1, 2, 3 }};

    std::cout << "last is " << get(xs, fin<3>::_2) << std::endl;

    size_t i {};
    std::cin >> i;

    choose<void, fin<3>>(
        to_fin<3>(i),
        []() { std::cout << "bad index" << std::endl; },
        [&](fin<3> ix) {
            std::cout << "it is " << get(xs, ix) << std::endl;
        }
    );

}