Re: VC8 compiler behavior?
Hello, Sam.
The code below does not compile with VC8.
I do not have VC8, so let's use comeau online:
First of all, small fixes:
#include <vector>
#include <iostream>
// move the operator below inside the namespace, then it will compile
....
template <class T>
std::ostream& operator<<(std::ostream& ostr, const std::vector<T>& v)
{
// output comma delimited vector elements ...
typename std::vector<T>::const_iterator end = v.end();
for (typename std::vector<T>::const_iterator it = v.begin(); it !=
end; ++it) {
ostr << *it;
if (it + 1 != end) ostr << ", ";
}
return ostr;
}
namespace formatter {
template <class T>
class bracketed {
public:
bracketed(const T& t) : value(t) {}
const T& value;
private:
// not implemented ...
bracketed<T>& operator=(const bracketed<T>&);
};
template <class T>
std::ostream& operator<<(std::ostream& ostr, const bracketed<T>& v)
{
// enclose value in brackets ...
return ostr << '[' << v.value << ']';
}
}
int main()
{
using formatter::bracketed;
// easy example ...
int x = 21014;
std::cout << bracketed<int>(x) << std::endl;
// more complicated example ...
std::vector<int> v;
v.push_back(2);
v.push_back(1);
v.push_back(0);
v.push_back(1);
v.push_back(4);
std::cout << bracketed<std::vector<int> >(v) << std::endl;
}
Now, if we try to compile this code with comeau online, we'll have
errors:
"ComeauTest.c", line 32: error: no operator "<<" matches these operands
operand types are: std::basic_ostream<char,
std::char_traits<char>> << const std::vector<int,
std::allocator<int>>
return ostr << '[' << v.value << ']';
^
detected during instantiation of "std::ostream
&formatter::operator<<(std::ostream &, const
formatter::bracketed<T> &) [with T=std::vector<int,
std::allocator<int>>]" at line 49
Ok, that's because you have templates and two-phase name lookup:
The first phase:
template <class T>
std::ostream& operator<<(std::ostream& ostr, const bracketed<T>& v)
{
// enclose value in brackets ...
return ostr << '[' << v.value << ']'; //(*)
}
In (*), compiler looks for operator << and finds only
std::ostream& operator<<(std::ostream& ostr, const bracketed<T>& v)
(after he finds it, compiler stops lookup and doesn't check enclosing
namespace (global)).
The second phase:
During the second stage compiler uses ADL and cannot find global
operator<<.
For example, if you change operator's name (operator >>), your example
will be compilable by comeau (yes, I know, such usage of operator >> is
stupid :) ):
#include <vector>
#include <iostream>
// move the operator below inside the namespace, then it will compile
....
template <class T>
std::ostream& operator<<(std::ostream& ostr, const std::vector<T>& v)
{
// output comma delimited vector elements ...
typename std::vector<T>::const_iterator end = v.end();
for (typename std::vector<T>::const_iterator it = v.begin(); it !=
end; ++it) {
ostr << *it;
if (it + 1 != end) ostr << ", ";
}
return ostr;
}
namespace formatter {
template <class T>
class bracketed {
public:
bracketed(const T& t) : value(t) {}
const T& value;
private:
// not implemented ...
bracketed<T>& operator=(const bracketed<T>&);
};
template <class T>
std::ostream& operator>>(std::ostream& ostr, const bracketed<T>& v)
{
// enclose value in brackets ...
return ostr << '[' << v.value << ']';
}
}
int main()
{
using formatter::bracketed;
// more complicated example ...
std::vector<int> v;
v.push_back(2);
v.push_back(1);
v.push_back(0);
v.push_back(1);
v.push_back(4);
std::cout >> bracketed<std::vector<int> >(v) << std::endl;
}
In strict mode, with -tused, Compile succeeded (but remember, the
Comeau online compiler does not link).
PS. I think, these changes will not help with VC8, AFAIK it does not
support two -phase name lookup.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]