c++ - 修复库代码出现编译错误的方法

标签 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 作为依赖项。我正在处理的具体错误是在 xutility 中,但我希望获得一些更一般的见解。

完整的错误信息如下:

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

提前致谢。

最佳答案

根据您显示的错误消息部分,我希望“合理”的代码是这样的:

#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);
}

您有错误的事实表明,很可能是您弄乱了“目标”参数。例如:

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++ 将此搜索的实现委托(delegate)给 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 中查找):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 为空,则不会打印任何内容。

关于c++ - 修复库代码出现编译错误的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34491186/

相关文章:

c++ - 推导重载函数的类型 - currying

c++ - typeid 是如何工作的,对象又是如何存储类信息的?

c++ - 如何计算存储在 map 中的 vector 中的元素数量

C++ Hello World 不显示输出

c++ - 如何在类中编写高效的正态分布

c++ - 中断分离的 boost::thread

c++ - 从 Wii 平衡板读取数据

visual-studio - Visual Studio 认为 `Microsoft Web Developer Tools` 已安装

.net - 为什么我无法附加到我的流程?

c++ - 使用 Boost.Signal 代替 Qt 的信号?没有moc吗?