修复库代码中出现的编译错误的方法

时间:2015-12-28 09:50:48

标签: c++ visual-studio boost visual-studio-2013

我正在尝试修复我的上一次编译错误,我遇到了其中一种情况,其中错误引用的行不在我编写的任何代码中,而是在其他标准库中。

显然,问题是由正在做的事情引起的(例如某些文件中的语法)但是,无法知道我的代码的哪一行正在调用导致该函数的函数错误。向后移动并不会更好,因为可以从我的代码中调用该函数任意次。

这样的东西:......

template<class _InIt,
    class _Ty> inline
    _InIt _Find(_InIt _First, _InIt _Last, const _Ty& _Val, false_type)
    {   // find first matching _Val
    for (; _First != _Last; ++_First)
        if (*_First == _Val)
            break;
    return (_First);
    }

只是没有告诉我如何继续。

我知道如果我能以某种方式退回编译过程以找到我的代码的最后一行,我可能会推断出这个问题。 (我试图增加编译器输出的日志记录详细程度,但它没有提供任何有用的信息)。

调试此类问题的最佳方法是什么?是否有一种方法可以像使用标准调试器或其他标准方法来解决问题一样逐步完成编译过程?或者这是必须通过个案处理的事情之一。

作为参考,我使用VS2013和boost 1.59.0以及sfml 2.3.2作为依赖项。我遇到的具体错误是多功能的,但我希望能有更多的一般见解。

以下是完整的错误消息:

Error 4 error C2678: binary '==' : no operator found which takes a
left-hand operand of type
'std::map<std::string,int,std::less<_Kty>,std::allocator<std::pair<const
_Kty,_Ty>>>' (or there is no acceptable conversion)     c:\program files (x86)\microsoft visual studio 12.0\vc\include\xutility 3026 1 Engine

提前致谢。

1 个答案:

答案 0 :(得分:2)

来自您显示的错误消息部分,我希望“理智”的代码是这样的:

#include <map>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;
using Map = map<string, int>;

int main() {
    vector<Map> maps;

    Map target { { "one", 1 }, { "two", 2 } };

    auto match = std::find(maps.begin(), maps.end(), target);
}

您有错误的事实,可能表示您搞砸了“目标”参数。 E.g:

auto match = std::find(maps.begin(), maps.end(), "one");

结果

error: invalid operands to binary expression ('std::map<std::__cxx11::basic_string<char>, int, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, int> > >' and 'const char *')
       { return *__it == _M_value; }

那是GCC / libstdc ++,它将此搜索的实现委托给find_if,因此细节不同。)

您可以在完整的错误消息中看到“堆栈”:

clang++-3.6   -DNDEBUG -std=c++14 -Wall -pedantic  -g -O3 -isystem /home/sehe/custom/nonius/include -isystem /home/sehe/custom/boost_1_60_0 -isystem /usr/include/python2.7 -I /tmp/autobahn-cpp/ -pthread -march=native -L /home/sehe/custom/boost_1_60_0/stage/lib/ -Wl,-rpath,/home/sehe/custom/boost_1_60_0/stage/lib  test.cpp   -o test
test.cpp:14:10: warning: unused variable 'match' [-Wunused-variable]
    auto match = std::find(maps.begin(), maps.end(), "one");
        ^
In file included from test.cpp:1:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/map:60:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/stl_tree.h:63:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/stl_algobase.h:71:
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/predefined_ops.h:194:17: error: invalid operands to binary expression ('std::map<std::__cxx11::basic_string<char>, int, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, int> > >' and 'const char *')
        { return *__it == _M_value; }
                ~~~~~ ^  ~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/stl_algo.h:120:8: note: in instantiation of function template specialization '__gnu_cxx::__ops::_Iter_equals_val<char const[4]>::operator()<__gnu_cxx::__normal_iterator<std::map<std::__cxx11::basic_string<char>, int, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, int> > > *, std::vector<std::map<std::__cxx11::basic_string<char>, int, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, int> > >, std::allocator<std::map<std::__cxx11::basic_string<char>, int, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, int> > > > > > >' requested here
        if (__pred(__first))
            ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/stl_algo.h:161:14: note: in instantiation of function template specialization 'std::__find_if<__gnu_cxx::__normal_iterator<std::map<std::__cxx11::basic_string<char>, int, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, int> > > *, std::vector<std::map<std::__cxx11::basic_string<char>, int, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, int> > >, std::allocator<std::map<std::__cxx11::basic_string<char>, int, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, int> > > > > >, __gnu_cxx::__ops::_Iter_equals_val<char const[4]> >' requested here
    return __find_if(__first, __last, __pred,
            ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/stl_algo.h:3790:19: note: in instantiation of function template specialization 'std::__find_if<__gnu_cxx::__normal_iterator<std::map<std::__cxx11::basic_string<char>, int, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, int> > > *, std::vector<std::map<std::__cxx11::basic_string<char>, int, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, int> > >, std::allocator<std::map<std::__cxx11::basic_string<char>, int, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, int> > > > > >, __gnu_cxx::__ops::_Iter_equals_val<char const[4]> >' requested here
    return std::__find_if(__first, __last,
                ^
test.cpp:14:23: note: in instantiation of function template specialization 'std::find<__gnu_cxx::__normal_iterator<std::map<std::__cxx11::basic_string<char>, int, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, int> > > *, std::vector<std::map<std::__cxx11::basic_string<char>, int, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, int> > >, std::allocator<std::map<std::__cxx11::basic_string<char>, int, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, int> > > > > >, char [4]>' requested here
    auto match = std::find(maps.begin(), maps.end(), "one");
                    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/stl_pair.h:214:5: note: candidate template ignored: could not match 'pair' against 'map'
    operator==(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/stl_iterator.h:292:5: note: candidate template ignored: could not match 'reverse_iterator' against 'map'
    operator==(const reverse_iterator<_Iterator>& __x,
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/stl_iterator.h:342:5: note: candidate template ignored: could not match 'reverse_iterator' against 'map'
    operator==(const reverse_iterator<_IteratorL>& __x,
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/stl_iterator.h:820:5: note: candidate template ignored: could not match '__normal_iterator' against 'map'
    operator==(const __normal_iterator<_IteratorL, _Container>& __lhs,
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/stl_iterator.h:827:5: note: candidate template ignored: could not match '__normal_iterator' against 'map'
    operator==(const __normal_iterator<_Iterator, _Container>& __lhs,
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/stl_iterator.h:1065:5: note: candidate template ignored: could not match 'move_iterator' against 'map'
    operator==(const move_iterator<_IteratorL>& __x,
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/stl_iterator.h:1071:5: note: candidate template ignored: could not match 'move_iterator' against 'map'
    operator==(const move_iterator<_Iterator>& __x,
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/ext/new_allocator.h:139:5: note: candidate template ignored: could not match 'new_allocator' against 'map'
    operator==(const new_allocator<_Tp>&, const new_allocator<_Tp>&)
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/allocator.h:128:5: note: candidate template ignored: could not match 'allocator' against 'map'
    operator==(const allocator<_T1>&, const allocator<_T2>&)
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/allocator.h:134:5: note: candidate template ignored: could not match 'allocator' against 'map'
    operator==(const allocator<_Tp>&, const allocator<_Tp>&)
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/stl_tree.h:324:5: note: candidate template ignored: could not match '_Rb_tree_iterator' against 'map'
    operator==(const _Rb_tree_iterator<_Val>& __x,
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/stl_tree.h:1273:5: note: candidate template ignored: could not match '_Rb_tree' against 'map'
    operator==(const _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __x,
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/postypes.h:216:5: note: candidate template ignored: could not match 'fpos' against 'map'
    operator==(const fpos<_StateT>& __lhs, const fpos<_StateT>& __rhs)
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/basic_string.h:4902:5: note: candidate template ignored: could not match 'basic_string' against 'map'
    operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/basic_string.h:4909:5: note: candidate template ignored: could not match 'basic_string' against 'map'
    operator==(const basic_string<_CharT>& __lhs,
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/basic_string.h:4923:5: note: candidate template ignored: could not match 'const _CharT *' against 'std::map<std::__cxx11::basic_string<char>, int, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, int> > >'
    operator==(const _CharT* __lhs,
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/basic_string.h:4935:5: note: candidate template ignored: could not match 'basic_string' against 'map'
    operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/array:240:5: note: candidate template ignored: could not match 'array' against 'map'
    operator==(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/tuple:915:5: note: candidate template ignored: could not match 'tuple' against 'map'
    operator==(const tuple<_TElements...>& __t,
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/stl_map.h:1052:9: note: candidate template ignored: could not match 'map<type-parameter-0-0, type-parameter-0-1, type-parameter-0-2, type-parameter-0-3>' against 'char const[4]'
        operator==(const map<_K1, _T1, _C1, _A1>&,
        ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/stl_multimap.h:974:5: note: candidate template ignored: could not match 'multimap' against 'map'
    operator==(const multimap<_Key, _Tp, _Compare, _Alloc>& __x,
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/stl_vector.h:1511:5: note: candidate template ignored: could not match 'vector' against 'map'
    operator==(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/random.tcc:2030:5: note: candidate template ignored: could not match 'normal_distribution' against 'map'
    operator==(const std::normal_distribution<_RealType>& __d1,
    ^
1 warning and 1 error generated.
<builtin>: recipe for target 'test' failed
make: *** [test] Error 1

提示:

  • 通常最好只检查代码中的顶级调用文档(test.cpp中为find):http://en.cppreference.com/w/cpp/algorithm/find
  • 无视被拒绝的候选人。 ADL的本质是,很多候选人显然不适用。这仅在您需要调试库代码以找出为什么您的operator==重载被拒绝时才有用。

开箱即用

如果我猜错了你的API滥用,这是一个建议的修复:

<强> Live On Coliru

#include <map>
#include <vector>
#include <string>
#include <algorithm>
#include <iostream>

using namespace std;
using Map = map<string, int>;

int main() {
    vector<Map> maps;

    Map target { { "one", 1 }, { "two", 2 } };

    auto match = std::find_if(maps.begin(), maps.end(), [](Map const& m) { return m.end() != m.find("one"); });

    if (match != maps.end()) {
        for (auto const& p : *match) {
            std::cout << p.first << " -> " << p.second << "\n";
        }
    }
}

当然,假设样本中maps为空,则不会打印任何内容。