2

ビットボードを使用するコードを書いています。ビットボードのすべてのビットを反復することは非常に一般的なアクションであるため、いくつかの反復子クラスを作成し、c++0x の範囲ベースのループを使用することにしました。beginただし、g++ (バージョン 4.6.3) は、 orに一致する関数がないことを教えてくれますend

私のコード:

#include <iostream>
#include <cinttypes>

class bitscan {
    uint64_t mask;
public:
    bitscan(uint64_t m) : mask(m) {}
    bool operator!=(bitscan it) const {return mask!=it.mask;}
    bitscan &operator++() {mask&=(mask-1);return *this;}
    int operator*() {return __builtin_ctzl(mask);}
};

bitscan begin(uint64_t m) {return m;}
bitscan end(uint64_t m) {return 0;}

int main() {
    uint64_t num=49;
    for (int i : num) std::cout<<i<<std::endl;
}

エラー:

err.cpp: In function ‘int main()’:
err.cpp:18:15: error: no matching function for call to ‘begin(long unsigned int&)’
err.cpp:18:15: note: candidates are:
/usr/include/c++/4.6/initializer_list:86:5: note: template<class _Tp> constexpr const _Tp* std::begin(std::initializer_list<_Tp>)
/usr/include/c++/4.6/bits/range_access.h:87:5: note: template<class _Tp, long unsigned int _Nm> _Tp* std::begin(_Tp (&)[_Nm])
/usr/include/c++/4.6/bits/range_access.h:58:5: note: template<class _Container> decltype (__cont.begin()) std::begin(const _Container&)
/usr/include/c++/4.6/bits/range_access.h:48:5: note: template<class _Container> decltype (__cont.begin()) std::begin(_Container&)
err.cpp:18:15: error: no matching function for call to ‘end(long unsigned int&)’
err.cpp:18:15: note: candidates are:
/usr/include/c++/4.6/initializer_list:96:5: note: template<class _Tp> constexpr const _Tp* std::end(std::initializer_list<_Tp>)
/usr/include/c++/4.6/bits/range_access.h:97:5: note: template<class _Tp, long unsigned int _Nm> _Tp* std::end(_Tp (&)[_Nm])
/usr/include/c++/4.6/bits/range_access.h:78:5: note: template<class _Container> decltype (__cont.end()) std::end(const _Container&)
/usr/include/c++/4.6/bits/range_access.h:68:5: note: template<class _Container> decltype (__cont.end()) std::end(_Container&)

ループを次の行に置き換えると、正常にfor (auto it=begin(num);it!=end(num);++it) std::cout<<*it<<std::endl; 動作します。

私の間違いは何ですか?

4

1 に答える 1

9

範囲ベースの for ステートメントでは、非メンバー関数beginend非メンバー関数は、引数依存のルックアップ(*) (C++11 §6.5.4/1) によってのみルックアップされます。これは、引数の型に関連付けられた名前空間でのみ見つかることを意味します (C++11 §3.4.2/2)。

のような基本的な型にuint64_tは名前空間が関連付けられていないため、その型はまったく見つからないbeginか、end見つかることはありません。をラップするクラス型を作成して、非メンバーと関数が引数依存のルックアップで見つかるようにする必要がuint64_tありbeginますend


(*) 注: 実際には 3 つの方法がbeginありend、これが見つかる可能性がありますが、これがシナリオに適用される唯一の方法です。begin配列や、およびという名前のメンバー関数を持つクラスには、特殊なケースもありますend

于 2012-06-27T21:30:04.187 に答える