无法使用非成员开始和结束功能编写范围

asa*_*elr 2 c++ for-loop g++ c++11 bitboard

我正在编写一个使用位板的代码.因为迭代位板的所有位是非常常见的动作,所以我决定编写一些迭代器类,并使用c ++ 0x的基于范围的循环.但是,g ++(版本4.6.3)告诉我,begin或者没有匹配的函数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;
}
Run Code Online (Sandbox Code Playgroud)

错误:

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&)
Run Code Online (Sandbox Code Playgroud)

如果我用线替换循环:for (auto it=begin(num);it!=end(num);++it) std::cout<<*it<<std::endl; 它工作正常.

我的错是什么?

Jam*_*lis 9

在基于范围的for语句中,仅通过依赖于参数的查找(*)(C++11§6.5.4/ 1)查找beginend非成员函数.这意味着它们只能在与参数类型相关联的命名空间中找到(C++11§3.4.2/ 2).

类似的基本类型uint64_t没有关联的命名空间,因此没有begin或者end永远不会找到它.您需要创建一个类类型来包装,uint64_t以便可以通过参数依赖查找找到非成员beginend函数.


(*)注:实际上有三种方法begin,并end可能发现,但是这是一个适用于您的方案的唯一途径.对于数组和具有名为begin和的成员函数的类,也有特殊情况end.

  • @asaelr这是一个简单的解决方案.而且,这是*非邪恶*解决方案. (2认同)