我昨天看到了一些有趣的编译器行为,我想我明白为什么会这样,但我想确定。所以,我不会写出我的推理,只是事实。
请注意,这不是我所包含的vector
而非string
的拼写错误。我故意这样做,以便编译器无法理解std :: string是什么,因此它必须搜索以找出+
所指的运算符:
#include <vector>
// #include <string> // intentionally commented out
template <typename T> struct A
{
A() { };
~A() { };
int m_member;
};
template <typename T> A<T> operator+(double lhs, const A<T> &rhs);
int main(int argc, char **argv)
{
std::string fullString = std::string("Hi ") + std::string("mom!");
}
因此,我在MS Visual Studio 2005中遇到了大量的编译器错误。我只展示了它们的一部分。
1>.\test.cpp(21) : error C2784: 'A<T> operator +(double,const A<T> &)' : could not deduce template argument for 'const A<T> &' from 'std::basic_string<_Elem,_Traits,_Ax>'
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>,
1> _Ax=std::allocator<char>
1> ]
1> .\test.cpp(16) : see declaration of 'operator +'
......错误继续......
1>.\test.cpp(21) : error C2784: 'std::_Vb_iterator<_MycontTy> std::operator +(_Vb_iterator<_MycontTy>::difference_type,std::_Vb_iterator<_MycontTy>)' : could not deduce template argument for 'std::_Vb_iterator<_MycontTy>' from 'std::basic_string<_Elem,_Traits,_Ax>'
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>,
1> _Ax=std::allocator<char>
1> ]
1> C:\Program Files (x86)\Microsoft Visual Studio 8\VC\include\vector(1800) : see declaration of 'std::operator +'
......错误继续......
1>.\test.cpp(21) : error C2784: 'std::_Vb_const_iterator<_MycontTy> std::operator +(_Vb_const_iterator<_MycontTy>::difference_type,std::_Vb_const_iterator<_MycontTy>)' : could not deduce template argument for 'std::_Vb_const_iterator<_MycontTy>' from 'std::basic_string<_Elem,_Traits,_Ax>'
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>,
1> _Ax=std::allocator<char>
1> ]
1> C:\Program Files (x86)\Microsoft Visual Studio 8\VC\include\vector(1695) : see declaration of 'std::operator +'
......错误继续......
1>.\test.cpp(21) : error C2784: 'std::_Vector_iterator<_Ty,_Alloc> std::operator +(_Vector_iterator<_Ty,_Alloc>::difference_type,std::_Vector_iterator<_Ty,_Alloc>)' : could not deduce template argument for 'std::_Vector_iterator<_Ty,_Alloc>' from 'std::basic_string<_Elem,_Traits,_Ax>'
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>,
1> _Ax=std::allocator<char>
1> ]
1> C:\Program Files (x86)\Microsoft Visual Studio 8\VC\include\vector(396) : see declaration of 'std::operator +'
......错误继续......
1>.\test.cpp(21) : error C2784: 'std::_Vector_const_iterator<_Ty,_Alloc> std::operator +(_Vector_const_iterator<_Ty,_Alloc>::difference_type,std::_Vector_const_iterator<_Ty,_Alloc>)' : could not deduce template argument for 'std::_Vector_const_iterator<_Ty,_Alloc>' from 'std::basic_string<_Elem,_Traits,_Ax>'
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>,
1> _Ax=std::allocator<char>
1> ]
1> C:\Program Files (x86)\Microsoft Visual Studio 8\VC\include\vector(264) : see declaration of 'std::operator +'
因此,编译器会搜索+
的含义并抱怨它无法推断出适当的模板参数。我对两个相关的事情感到惊讶,一个是它为每个涉及模板的重载+
运算符提供此错误。这告诉我,编译器完全没有办法排除这些+
中的任何一个都没有意义; 两个,这是相关的,它不仅仅抱怨没有合适的运营商。
我认为这是一个了解模板如何实例化和编译的机会。有没有人有任何好的解释或参考?
答案 0 :(得分:2)
事实上,由于无法找到匹配项,因此使用错误告诉您实际找到的可能的运算符候选项。
例如,g ++错误告诉你它找不到运算符然后提供相同的消息,但是在“候选者是:”形式而不是每个运算符一个错误。
这样做是为了帮助:由于无法找到匹配项,因此假定您实际上可能意味着任何可能的运算符。
答案 1 :(得分:2)
请注意,这不是我所包含的
vector
而非string
的拼写错误。我故意这样做,以便编译器无法理解std :: string是什么,因此它必须搜索+
来指出我所指的是哪个运算符。
这不正确。编译器 知道std::string
是什么。例如,考虑以下程序编译得很好(使用Visual C ++ 2010,但它也应该在2005年工作):
#include <vector>
int main() {
std::string s;
}
使用Visual C ++时(至少是Visual C ++ 2005到2010;我不能代表其他版本),包括<vector>
也包括任何内部头部声明并定义std::basic_string
和{{1} }。这是C ++ langauge标准所允许的。
但是,您显然没有获得std::string
(或更准确地说,operator+
)操作数的std::string
重载。要获得那些,您必须包含std::basic_string
。
编译器完全清楚<string>
是什么,但是当它试图为两个std::string
对象找到operator+
重载时,它会失败并报告所有std::string
它考虑但是被拒绝的重载。
答案 2 :(得分:1)
它并不只是抱怨没有合适的运营商。
这就是IMO一个简单的愚蠢的编译器行为,如果发生了这种情况。当然它应该首先告诉你什么是错的(即没有合适的运算符存在),然后列出所有考虑的模板。
一个是它为每个涉及模板的重载+运算符提供此错误。这告诉我编译器完全没有办法排除任何这些+没有意义;
通常,它不能这样做,因为例如std::_Vector_iterator<_Ty,_Alloc>
可能是std::basic_string<>
的基类,这意味着一个运算符重载可能是可行的并且演绎成功。参数推导是在那个阶段编译C ++的阶段,它将这些事情计算出来,编译器只会向你报告参数推导的结果。