Search code examples
c++templatescompiler-errors

With templates: Operator resolved first or conversion resolved first?


I saw some interesting compiler behavior yesterday and I think I understand why it's happening, but I want to be sure. So, I'm not going to write my reasoning, just the facts.

Note, it's not a typo that I've included vector instead of string. I did it intentionally so that the compiler would not be able to understand what an std::string was and so that it would have to search around to figure out which operator I'm referring to by +:

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

So, I get a slew of compiler errors in MS Visual Studio 2005. I'm only showing a subset of them.

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 +'

... errors continued ...

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 +'

... errors continued ...

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 +'

... errors continued ...

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 +'

... errors continued ...

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 +'

So, the compiler searches around for the what the + means and complains that it can't deduce the appropriate template arguments. I'm surprised by two related things, one is that it gives this error for each overloaded + operator that involves templates. This tells me that the compiler has absolutely no way of ruling out that any of these + are not meaningful; two, which is related, that it doesn't just complain that no suitable operator exists.

I see this as an opportunity to learn something about how templates are instantiated and compiled. Does anyone have any good explanation or references?


Solution

  • In fact, since it couldn't find a match it's using the errors to tell you the possible operator candidates it actually found.

    The g++ error for example tells you that it can't find the operator and then provides the same slew of messages, but in "candidates are:" form rather than one error per operator.

    It's doing this in an attempt to be helpful: Since it couldn't find a match it assumes you may have actually meant any of the possible available operators.