8

深く編集された要素をdeep_flatten生成する関数テンプレートを作成したかったのです。たとえば、ネストされたsのみを考慮すると、次のようになります。rangejoinstd::vector

template <typename T>
struct is_vector : public std::false_type { };

template <typename T, typename A>
struct is_vector<std::vector<T, A>> : public std::true_type { };

template <typename T>
auto deepFlatten(const std::vector<std::vector<T>>& vec) {
    using namespace std::ranges;
    if constexpr (is_vector<T>::value) {
        auto range = vec | views::join;
        return deepFlatten(std::vector(range.begin(), range.end()));
    } else {
        auto range = vec | views::join;
        return std::vector(range.begin(), range.end());
    }
}

これにより、次のことが可能になります。

std::vector<std::vector<std::vector<int>>> nested_vectors = {
        {{1, 2, 3}, {4, 5}, {6}},
        {{7},       {8, 9}, {10, 11, 12}},
        {{13}}
};

std::ranges::copy(
        deep_flatten(nested_vectors),
        std::ostream_iterator<int>(std::cout, " ")
);

予想どおり、次のテキストがコンソールに出力されます。

1 2 3 4 5 6 7 8 9 10 11 12 13

しかし、私はこの解決策があまり好きではありません。非効率的であるだけでなく(多数の一時的なベクトルを作成する)、std::vectors でのみ機能します。の魔法をもう少し使用して、std::ranges::range概念を使用できると考えました。

namespace rng {
    template <std::ranges::range Rng>
    auto deep_flatten(Rng&& rng) {
        using namespace std::ranges;

        if constexpr (range<Rng>) {
            return deep_flatten(rng | views::join);
        } else {
            return rng | views::join;
        }
    }
}

これは非常に簡単に思えましたstd::ranges::range。ネストされた範囲であるかどうかに応じて、joined 要素を再帰するか、単に返します。

残念ながら、うまくいきません。実行しようとした後:

int main() {
    std::set<std::vector<std::list<int>>> nested_ranges = {
            {{1, 2, 3}, {4, 5}, {6}},
            {{7},       {8, 9}, {10, 11, 12}},
            {{13}}
    };

    std::ranges::copy(
            rng::deep_flatten(nested_ranges),
            std::ostream_iterator<int>(std::cout, " ")
    );
}

次のようなエラーが表示されます。

In instantiation of 'auto rng::deep_flatten(Rng&&) [with Rng = std::ranges::join_view<std::ranges::ref_view<std::set<std::vector<std::__cxx11::list<int> > > > >]':
     required from 'auto rng::deep_flatten(Rng&&) [with Rng = std::set<std::vector<std::__cxx11::list<int> > >&]'
     required from here
     error: use of 'auto rng::deep_flatten(Rng&&) [with Rng = std::ranges::join_view<std::ranges::ref_view<std::set<std::vector<std::__cxx11::list<int> > > > >]' before deduction of 'auto'
     39 |             return deep_flatten(rng | views::join);
        |                    ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~

同様の問題を調査した結果、エラーがここに表示される理由がわかりません。

私は使っているgcc version 10.1.0 (Rev3, Built by MSYS2 project)

4

1 に答える 1