1

を使用して双方向イテレータを使用するコンテナ用の汎用リバース ラッパーを作成しようとしていますstd::reverse_iterator

ただし、コンパイラがbegin(...)orを検索すると、候補が 0 の引数を期待しているのに 1 が提供されているためend(...)、一致する関数呼び出しが見つからないと言うようです。reverse_wrapper<CONTAINER>::begin(container)

これは存在しないためだstd::begin(myArray&)と思いました。std::end(myArray&)それらを名前空間に強制してもstd機能しませんでした(とにかくお勧めできません)。std::また、私からプレフィックスを削除しようとしましたreverse_wrapperが、それは機能せず、機能しているstdコンテナーの実装も壊れます。

これはスコープ解決の問題のようですが、修正できないようです。私は何を間違っていますか?

コード:

#include <iterator>
#include <iostream>
#include <vector>

#define Fn1 0 // std container WORKS
#define Fn2 1 // non-std container DOESN'T WORK

template <typename Container>
struct reverse_wrapper
{
    Container& container;

    auto begin()
        -> std::reverse_iterator< decltype(std::end(container)) >
    {
        return std::reverse_iterator< decltype(std::end(container)) >(std::end(container));
    }

    auto end()
        -> std::reverse_iterator< decltype(std::begin(container)) >
    {
        return std::reverse_iterator< decltype(std::begin(container)) >(std::begin(container));
    }
};

template <typename Container>
auto reverse(Container&& container)
-> reverse_wrapper<Container>
{
    return{ container };
}

struct myArray
{
    int elements[5] = {1,2,3,4,5};
};

int* begin(myArray& array) { return &array.elements[0]; }
int*   end(myArray& array) { return &array.elements[5]; }

#if Fn1
void fn1()
{
    std::vector<int> x = { 1,2,3,4,5 };
    for (auto& ix : reverse(x))
    {
        std::cout << ix << std::endl;
    }
    std::cout << "-----" << std::endl;
    for (auto& ix : x)
    {
        std::cout << ix << std::endl;
    }
}
#endif

#if Fn2
void fn2()
{
    myArray x;
    for (auto& ix : reverse(x))
    {
        std::cout << ix << std::endl;
    }
    std::cout << "-----" << std::endl;
    for (auto& ix : x)
    {
        std::cout << ix << std::endl;
    }
}
#endif

int main()
{
#if Fn1
    fn1();
#endif
#if Fn2
    fn2();
#endif
}

エラー:

「struct reverse_wrapper」のインスタンス化:
61:30: ここから必須
14:56: エラー: 'end(myArray&)' の呼び出しに一致する関数がありません
14:56: 注: 候補者は:
/usr/include/c++/4.9/string:51:0 からインクルードされたファイルで、
                 /usr/include/c++/4.9/bits/locale_classes.h:40 から、
                 /usr/include/c++/4.9/bits/ios_base.h:41 から、
                 /usr/include/c++/4.9/ios:42 から、
                 /usr/include/c++/4.9/ostream:38 から、
                 /usr/include/c++/4.9/iterator:64 から、
                 1から:
/usr/include/c++/4.9/bits/range_access.h:68:5: 注意: テンプレート decltype (__cont.end()) std::end(_Container&)
     end(_Container& __cont) -> decltype(__cont.end())
     ^
/usr/include/c++/4.9/bits/range_access.h:68:5: 注: テンプレート引数の推定/置換に失敗しました:
/usr/include/c++/4.9/bits/range_access.h: 'template decltype (__cont.end()) std::end(_Container&) [with _Container = myArray]' の代わりに:
14:56: 「struct reverse_wrapper」から必要
61:30: ここから必須
/usr/include/c++/4.9/bits/range_access.h:68:5: エラー: 'struct myArray' には 'end' という名前のメンバーがありません
 「struct reverse_wrapper」のインスタンス化:
61:30: ここから必須
/usr/include/c++/4.9/bits/range_access.h:78:5: 注意: テンプレート decltype (__cont.end()) std::end(const _Container&)
     end(const _Container& __cont) -> decltype(__cont.end())
     ^
/usr/include/c++/4.9/bits/range_access.h:78:5: 注: テンプレート引数の推定/置換に失敗しました:
/usr/include/c++/4.9/bits/range_access.h: 'template decltype (__cont.end()) std::end(const _Container&) [with _Container = myArray]' の代わりに:
14:56: 「struct reverse_wrapper」から必要
61:30: ここから必須
/usr/include/c++/4.9/bits/range_access.h:78:5: エラー: 'const struct myArray' には 'end' という名前のメンバーがありません
 「struct reverse_wrapper」のインスタンス化:
61:30: ここから必須
/usr/include/c++/4.9/bits/range_access.h:97:5: 注意: テンプレート _Tp* std::end(_Tp (&)[_Nm])
     end(_Tp (&__arr)[_Nm])
     ^
/usr/include/c++/4.9/bits/range_access.h:97:5: 注: テンプレート引数の推定/置換に失敗しました:
14:56: 注: タイプ「_Tp [_Nm]」と「myArray」が一致しません
/usr/include/c++/4.9/bits/basic_string.h:42:0 からインクルードされたファイルで、
                 /usr/include/c++/4.9/string:52 から、
                 /usr/include/c++/4.9/bits/locale_classes.h:40 から、
                 /usr/include/c++/4.9/bits/ios_base.h:41 から、
                 /usr/include/c++/4.9/ios:42 から、
                 /usr/include/c++/4.9/ostream:38 から、
                 /usr/include/c++/4.9/iterator:64 から、
                 1から:
/usr/include/c++/4.9/initializer_list:99:5: 注意: テンプレート constexpr const _Tp* std::end(std::initializer_list)
     end(initializer_list __ils) noexcept
     ^
/usr/include/c++/4.9/initializer_list:99:5: 注: テンプレート引数の推定/置換に失敗しました:
14:56: 注: 「myArray」は「std::initializer_list」から派生したものではありません
20:58: エラー: 「begin(myArray&)」の呼び出しに一致する関数がありません
20:58: 注: 候補者は:
/usr/include/c++/4.9/string:51:0 からインクルードされたファイルで、
                 /usr/include/c++/4.9/bits/locale_classes.h:40 から、
                 /usr/include/c++/4.9/bits/ios_base.h:41 から、
                 /usr/include/c++/4.9/ios:42 から、
                 /usr/include/c++/4.9/ostream:38 から、
                 /usr/include/c++/4.9/iterator:64 から、
                 1から:
/usr/include/c++/4.9/bits/range_access.h:48:5: 注意: テンプレート decltype (__cont.begin()) std::begin(_Container&)
     begin(_Container& __cont) -> decltype(__cont.begin())
     ^
/usr/include/c++/4.9/bits/range_access.h:48:5: 注: テンプレート引数の推定/置換に失敗しました:
/usr/include/c++/4.9/bits/range_access.h: 'template decltype (__cont.begin()) std::begin(_Container&) [with _Container = myArray]' の代わりに:
20:58: 「struct reverse_wrapper」から必要
61:30: ここから必須
/usr/include/c++/4.9/bits/range_access.h:48:5: エラー: 'struct myArray' には 'begin' という名前のメンバーがありません
 「struct reverse_wrapper」のインスタンス化:
61:30: ここから必須
/usr/include/c++/4.9/bits/range_access.h:58:5: 注意: テンプレート decltype (__cont.begin()) std::begin(const _Container&)
     begin(const _Container& __cont) -> decltype(__cont.begin())
     ^
/usr/include/c++/4.9/bits/range_access.h:58:5: 注: テンプレート引数の推定/置換に失敗しました:
/usr/include/c++/4.9/bits/range_access.h: 'template decltype (__cont.begin()) std::begin(const _Container&) [with _Container = myArray]' の代わりに:
20:58: 「struct reverse_wrapper」から必要
61:30: ここから必須
/usr/include/c++/4.9/bits/range_access.h:58:5: エラー: 'const struct myArray' には 'begin' という名前のメンバーがありません
 「struct reverse_wrapper」のインスタンス化:
61:30: ここから必須
/usr/include/c++/4.9/bits/range_access.h:87:5: 注意: テンプレート _Tp* std::begin(_Tp (&)[_Nm])
     begin(_Tp (&__arr)[_Nm])
     ^
/usr/include/c++/4.9/bits/range_access.h:87:5: 注: テンプレート引数の推定/置換に失敗しました:
20:58: 注: タイプ「_Tp [_Nm]」と「myArray」が一致しません
/usr/include/c++/4.9/bits/basic_string.h:42:0 からインクルードされたファイルで、
                 /usr/include/c++/4.9/string:52 から、
                 /usr/include/c++/4.9/bits/locale_classes.h:40 から、
                 /usr/include/c++/4.9/bits/ios_base.h:41 から、
                 /usr/include/c++/4.9/ios:42 から、
                 /usr/include/c++/4.9/ostream:38 から、
                 /usr/include/c++/4.9/iterator:64 から、
                 1から:
/usr/include/c++/4.9/initializer_list:89:5: 注意: テンプレート constexpr const _Tp* std::begin(std::initializer_list)
     begin(initializer_list __ils) noexcept
     ^
/usr/include/c++/4.9/initializer_list:89:5: 注: テンプレート引数の推定/置換に失敗しました:
20:58: 注: 「myArray」は「std::initializer_list」から派生したものではありません
 関数 'void fn2()' 内:
61:30: エラー: タイプ 'reverse_wrapper' の式からのタイプ 'myArray&' の参照の無効な初期化
38:6: 注: 「int* begin(myArray&)」の引数 1 を渡す際に
61:30: エラー: タイプ 'reverse_wrapper' の式からのタイプ 'myArray&' の参照の無効な初期化
39:8: 注: 'int* end(myArray&)' の引数 1 を渡す際に
 

Demo

4

2 に答える 2

3

コメントに応えて、自動的に推定される戻り値の型がないことの回避策を書きましょう。

要約すると、問題は、実装をバックアップとして使用しているときに、名前空間で修飾された呼び出しを使用していて、begin実際endには最適なものを単純に呼び出していることです。std::

コメントで提案した解決策は機能しないため、これを試すことができます。

を含むヘッダーでreverse_wrapper、このメソッドを追加できます

namespace detail {
    using std::begin;
    using std::end;
    template< typename Container >
    auto impl_begin( Container & c ) -> decltype( begin(c) ) {
         return begin(c);
    }
    // Same for end
}

template< typename Container >
class reverse_wrapper {
    Container& container;
public:
    auto end() -> decltype( detail::impl_begin(container) ) {
        return std::reverse_iterator<decltype( detail::impl_begin(container) )>( detail::impl_begin(container) );
    }
    // ... and the rest
};
于 2016-07-19T17:20:02.063 に答える