C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

VC8 compiler behavior?

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Sam Stump
Guest





PostPosted: Tue Aug 22, 2006 5:33 am    Post subject: VC8 compiler behavior? Reply with quote



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! ]
Back to top
Jack Klein
Guest





PostPosted: Tue Aug 22, 2006 7:21 pm    Post subject: Re: VC8 compiler behavior? Reply with quote



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

Quote:
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! ]
Back to top
Hrayr BABAJANYAN
Guest





PostPosted: Tue Aug 22, 2006 7:24 pm    Post subject: Re: VC8 compiler behavior? Reply with quote



Hi,
Sam Stump wrote:
Quote:
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;
}


The following simplified code emulates the problem:

// >>>>>>>>> begin
namespace M
{
class A {};
class B {};
void f(A, int);
}

void f(M::A, M::B);

namespace N
{
struct D
{
M::B b;
};

void f(M::A a, D d)
{
f(a, d.b);
// should look in current namespace, in namespace M
// where A is declared and in global namespace (but does not)

// error message in VC8:
// error C2665: 'N::f' : none of the 2 overloads could convert all
the argument types
// could be 'void M::f(M::A,int)' [found using argument-dependent
lookup]
// or 'void N::f(M::A,N:Very Happy)'
}
}

int main()
{
f(M::A(), N:Very Happy());
return (0);
}
// <<<<<<<<< end

It look really strange to me (looks mor like a bug) that the name
lookup
algorithm does not find the matching global function
(3.4.2 Argument-dependent name lookup [basic.lookup.koenig])

"...the set of declarations found by the lookup of the function name
is the union of the set of declarations found using ordinary
unqualified
lookup and the set of declarations found in the namespaces and classes
associated with the argument types."

(BTW: the same problem is present while compiling with gcc 3.2.2)

Cheers!
--
Hrayr


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





PostPosted: Tue Aug 22, 2006 7:28 pm    Post subject: Re: VC8 compiler behavior? Reply with quote

Quote:
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! ]
Back to top
Earl Purple
Guest





PostPosted: Tue Aug 22, 2006 7:28 pm    Post subject: Re: VC8 compiler behavior? Reply with quote

Sam Stump wrote:

Quote:
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! ]
Back to top
Sam
Guest





PostPosted: Tue Aug 22, 2006 8:37 pm    Post subject: Re: VC8 compiler behavior? Reply with quote

{ overquoted sigs trimmed. -mod }

Jack Klein wrote:
Quote:
On 21 Aug 2006 20:33:28 -0400, Sam Stump
sMaUmDuDeYlS.HsOtEuSmp (AT) verizon (DOT) 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

Thanks for the advice, but that IS the implementation's identifier, not
mine!

Sam


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





PostPosted: Tue Aug 22, 2006 8:38 pm    Post subject: Re: VC8 compiler behavior? Reply with quote

Sam Stump wrote:
Quote:
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;
}

Is conformant.

The "global namespace" doesn't participate in the name lookup, so you
have to give your function a hint, like:

template <class T>
std::ostream& operator<<(std::ostream& ostr, const bracketed<T>& v)
{
using ::operator << ;
return ostr << '[' << v.value << ']';
}


HTH


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





PostPosted: Tue Aug 22, 2006 8:51 pm    Post subject: Re: VC8 compiler behavior? Reply with quote

Jack Klein wrote:
Quote:
On 21 Aug 2006 20:33:28 -0400, Sam Stump
sMaUmDuDeYlS.HsOtEuSmp (AT) verizon (DOT) 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.

His code doesn't. Thanks to templates, the actual error occurs
somewhere in the instatiation of a template in the standard
library. Since the standard library is part of the
implementation, it has a right to these identifiers, and in
fact, must use them for any symbol not defined in the standard
library.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


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





PostPosted: Tue Aug 22, 2006 10:23 pm    Post subject: Re: VC8 compiler behavior? Reply with quote

dasjotre wrote:

Quote:
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.

According to §3.4.2, you've got it backwards. The compiler
should only apply ADL to increase the set of callable functions.
Of course, templates change the rules somewhat. I'll admit that
I don't understand the rules well enough to be sure, but from my
reading of §14.6.4.2, I would have though his code legal, since
the function he is looking for is delcared before the template
definition, and is visible in the templat definition context.

Still, g++ disagrees with me, and from experience, it's right
more often than I am. But I would like an explication as to why
the standard unqualified lookup in the template definition
context doesn't find the operator, or why this lookup isn't used
in this case.

Quote:
// 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)

Which is formally banned. Worse, it means that other users will
see it, which you definitly want to avoid.

Personally, I think the preferred solution would be to create a
class comma_separated_list (where the actual character used for
the comma is locale dependant), along the lines of bracketed,
and use that.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


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





PostPosted: Wed Aug 23, 2006 4:54 am    Post subject: Re: VC8 compiler behavior? Reply with quote

On 22 Aug 2006 13:23:25 -0400, "kanze" <kanze@gabi-soft.fr> wrote:

Quote:
I'll admit that
I don't understand the rules well enough to be sure,

Who does :-)

Quote:
but from my
reading of §14.6.4.2, I would have though his code legal, since
the function he is looking for is delcared before the template
definition, and is visible in the templat definition context.

The issue is what is visible from the context of

std::ostream& operator<<(std::ostream&, const bracketed<T>&) (*)

Of course both std and formatter are associated with "v.value" within
it. As to the other user-defined operator<< (the one for vectors), it
is in the global namespace but it is never invoked with arguments
whose type is declared there, so in this example it is never found via
ADL (and it can't be found by unqualified lookup either, as it is
invoked from a function that has its same name).

More in detail, let's consider the original code and, in order of
appearance, the two calls in main(); the issue is resolving the call
having v.value as right-hand expression

(1) v.value has type int: unqualified lookup finds (*) itself;
ADL finds (*) again and the std version, which is clearly the
best match.

(2) v.value has type vector<int> but nothing has changed from
the point of view of lookup: the candidates are the same as
in the previous case. Obviously there's no match.

When the first user-defined operator<< is moved into namespace
formatter that namespace kicks in as associated namespace for v.value,
which explains the successful resolution. In short if it works it's
always due to ADL, as ordinary lookup never finds the right choice: it
always finds itself.

This is an analogous, simpler, example, where "<<" is actually named
"f":

#include <ostream>
#include <iostream>

void f(int) {}

namespace S {

struct X { int a; X() : a(0) {} };

template <typename T>
void f(const T& t)
{
f(t.a); // doesn't find f(int)
}

}

int main()
{
S::X x;
f(x);
}


PS: I intentionally omitted that in the original code <ostream> should
be included; it also misses a couple of typename-s. Strictly speaking
it invokes undefined behavior.

--
Gennaro Prota

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






PostPosted: Wed Aug 23, 2006 6:32 pm    Post subject: Re: VC8 compiler behavior? Reply with quote

Hello, Sam.
Quote:
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 Smile ):

#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! ]
Back to top
Pete Becker
Guest





PostPosted: Wed Aug 23, 2006 6:33 pm    Post subject: Re: VC8 compiler behavior? Reply with quote

Jack Klein wrote:

Quote:
On 21 Aug 2006 20:33:28 -0400, Sam Stump
sMaUmDuDeYlS.HsOtEuSmp (AT) verizon (DOT) 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.


That _Ty is in the library implementation, not the user's code. It shows
up in the error messages to explain what type the template's formal
argument was bound to.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.