From: Sam Stump on
The code below does not compile with VC8. The error is:

sample.cpp(36) : error C2679: binary '<<' : no operator found which takes
a right-hand operand of type 'const std::vector<_Ty>' (or there is no
acceptable conversion)
with
[
_Ty=int
]

but it is clearly there. Is this conformant behavior or a bug?

================= begin code =====================
// sample.cpp

#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 ...
std::vector<T>::const_iterator end = v.end();
for (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;
}

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: dasjotre on
compiler first looks at the enclosing namespace and then into std
namespace because vector template is from there (ADL) and it finds
many '<<' operators that don't fit the purpose. because of the ADL
rules it doesn't look any further.

> // move the operator below inside the namespace, then it will compile ...

and that would be the solution for it (the most complete solution
would be putting it inside std namespace)

<snip>


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: dasjotre on
>> and that would be the solution for it (the most complete solution would
be
>> putting it inside std namespace)
don't!


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Earl Purple on

Sam Stump wrote:

> The code below does not compile with VC8. The error is:
>
> sample.cpp(36) : error C2679: binary '<<' : no operator found which takes
> a right-hand operand of type 'const std::vector<_Ty>' (or there is no
> acceptable conversion)
> with
> [
> _Ty=int
> ]
>
> but it is clearly there. Is this conformant behavior or a bug?
>
================= begin code =====================
> // sample.cpp
>
> #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 ...
> std::vector<T>::const_iterator end = v.end();
> for (std::vector<T>::const_iterator it = v.begin(); it != end; ++it) {
> ostr << *it;
> if (it + 1 != end) ostr << ", ";
> }
> return ostr;
> }


//etc
As far as I am aware this is conformant, you can only overload
operators if one of the types is your own, and neither of them are,
because vector belongs in namespace std. You should therefore write a
wrapper. For output this is easy enough.

template < typename SEQ >
class const_sequence_wrapper
{
public:
// put some typedefs here

const SEQ & seq;
/*explicit*/ const_sequence_wrapper( const SEQ & seq_in ) : seq(
seq_in )
{
}

// define begin() and end()
};

then implement operator<< in terms of that. In fact now we've created a
wrapper for the purpose of printing, we can specialise it with extra
parameters regarding how we will output it, eg what delimiter we use,
any "beginning of sequence" and "end of sequence" markers (the latter
is particularly useful).

You may wish, for example, to use tab as delimiter and new-line as
end-of-sequence.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Jack Klein on
On 21 Aug 2006 20:33:28 -0400, Sam Stump
<sMaUmDuDeYlS.HsOtEuSmp(a)verizon.net> wrote in comp.lang.c++.moderated:

> The code below does not compile with VC8. The error is:
>
> sample.cpp(36) : error C2679: binary '<<' : no operator found which takes
> a right-hand operand of type 'const std::vector<_Ty>' (or there is no
> acceptable conversion)
> with
> [
> _Ty=int
> ]
>
> but it is clearly there. Is this conformant behavior or a bug?

[snip]

Almost certainly not the problem you are questioning, but your program
is ill-formed and has undefined behavior. Your code is not allowed to
define identifiers with a leading underscore followed by an upper case
latter, or containing two consecutive underscores anywhere within
them.

All identifiers fitting these patterns are reserved for the
implementation in all contexts.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]