implicit conversion fails in function parameter

443 views Asked by At
#include <iostream>
#include <string>

int main() {
    using std::string;
    using std::distance;
    using std::cout;
    using std::endl;

    string s("abc");
    string::const_iterator b = s.begin();
    string::const_iterator e = s.end(); // success
    cout << distance(b, e) << endl;
    cout << distance(b, static_cast<string::const_iterator>(s.end())) << endl;
    cout << distance(b, s.end()) << endl; // error
    return 0;
}

End of the string s.end() can be implicitly converted to std::string::const_iterator as e, but when it is passed as function parameter, it has to be explicitly casted; otherwise an error is raised in compile time. Why is that?

FYI, s.begin() and s.end() both seem to return std::string::iterator.

An expression e is said to be implicitly convertible to T2 if and only if T2 can be copy-initialized from e, that is the declaration T2 t = e; is well-formed (can be compiled), for some invented temporary t.

2

There are 2 answers

0
Vlad from Moscow On BEST ANSWER

The function has one template parameter

template <class InputIterator> 
typename iterator_traits<InputIterator>::difference_type 
distance(InputIterator first, InputIterator last); 

So it can not deduce the type of the template parameter because either iterator const or non-const can be used for each function parameter.

You could write without casting the following way

std::distance<std::string::const_iterator>(b, s.end()) 

explicitly specifying the template argument.

Another example. This code snippet also will not compile

long x = 0;
int y = 0;
std::min(x, y);

However if you will write

long x = 0;
int y = 0;
std::min<long>(x, y);

then the code compiles.

0
Pete Becker On

Template function arguments don't get converted. The two arguments to std::distance are required to be the same type.