Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

bogus error C2228

3 views
Skip to first unread message

Mike Loftus

unread,
Apr 7, 2003, 11:13:12 AM4/7/03
to
Within a callback for a button in a dialog, I have
code like this:

Foo foo(filename);
int count = foo.get_count();

The error is generated for the second line above complaining
that the object (foo) is not a class (it is indeed).

This code does compile:

Foo *foo(filename);
int count = foo->get_count();
delete foo;

Why does the first version fail and the second succeed?

[Visual C++ .NET Version 7.0.9466]

--
Mike Loftus (real email address does not contain error)
Ford Scientific Research Lab
Expressing my personal opinions, not necessarily those of Ford Motor Co.


Mike Loftus

unread,
Apr 7, 2003, 3:38:59 PM4/7/03
to
"Mike Loftus" <mlof...@ford.error.com> wrote in message
news:b6s4i9$la...@eccws12.dearborn.ford.com...

> Within a callback for a button in a dialog, I have
> code like this:
>
> Foo foo(filename);
> int count = foo.get_count();
>
> The error is generated for the second line above complaining
> that the object (foo) is not a class (it is indeed).
>
> This code does compile:
>
> Foo *foo(filename);
> int count = foo->get_count();
> delete foo;
>
> Why does the first version fail and the second succeed?
>
> [Visual C++ .NET Version 7.0.9466]

Must be a compiler bug.


Here is a little more detail.
This fails on line 3 with C2228:

CString filename;
Foo foo(string(filename)); // Foo CTOR takes a std::string
int count = foo.get_count(); // compiler error C2228


This is worse failing with C2061, C2066, and C2059 on line 2:

CString filename;
Foo foo((string(filename))); // multiple compiler errors

[Since when are additional parenthesis illegal?]


This does work:

CString filename;
string filename_string(filename); // unnecessary object
Foo foo(filename_string);
int count = foo.get_count();


Go figure.

Anyway, throwing error C2228 is misleading, to say the least.

Craig Powers

unread,
Apr 7, 2003, 5:36:15 PM4/7/03
to
Mike Loftus wrote:
>
> Here is a little more detail.
> This fails on line 3 with C2228:
>
> CString filename;
> Foo foo(string(filename)); // Foo CTOR takes a std::string
> int count = foo.get_count(); // compiler error C2228

You declared a function foo returning a Foo and taking a string
argument named filename in line two. This is a somewhat well-known
gotcha with C++. When you see it come up enough times, you learn to
recognize it.

(The usual answer to it is to use additional parens, which according
to your additional comment [elided] produces other errors)

--
Craig Powers
MVP - Visual C++

Visual C++ Team

unread,
Apr 8, 2003, 1:34:40 PM4/8/03
to
Hi Mike,
I reproed the steps you gave below in the most elemental way - created
simple class Foo which took char* as constructor param and a simple method
representing GetCount(). Both versions of below compile and run without
issue on my build of VC .Net 7.1 RC1 2215. Are you using managed extensions
or standard C++ syntax? Do you have standard C++ compiling with the /clr
switch turned on? Reason I ask is that the syntax for the get_count() looks
a lot like managed syntax of a property and not just a method. It would help
to know more about your project configurations and the libs you're using in
giving this question the attention it deserves.

--
Robert Svilpa
Visual C++
This posting is provided "AS IS" with no warranties, and confers no rights.


"Mike Loftus" <mlof...@ford.error.com> wrote in message
news:b6s4i9$la...@eccws12.dearborn.ford.com...

Mike Loftus

unread,
Apr 9, 2003, 10:16:46 AM4/9/03
to
"Visual C++ Team" <vc...@microsoft.com> wrote in message
news:#qJ5iUf$CHA....@TK2MSFTNGP10.phx.gbl...

> Hi Mike,
> I reproed the steps you gave below in the most elemental way - created
> simple class Foo which took char* as constructor param and a simple method
> representing GetCount(). Both versions of below compile and run without
> issue on my build of VC .Net 7.1 RC1 2215. Are you using managed
extensions
> or standard C++ syntax? Do you have standard C++ compiling with the /clr
> switch turned on? Reason I ask is that the syntax for the get_count()
looks
> a lot like managed syntax of a property and not just a method. It would
help
> to know more about your project configurations and the libs you're using
in
> giving this question the attention it deserves.
>
>
> "Mike Loftus" <mlof...@ford.error.com> wrote in message
> news:b6s4i9$la...@eccws12.dearborn.ford.com...
> > Within a callback for a button in a dialog, I have
> > code like this:
> >
> > Foo foo(filename);
> > int count = foo.get_count();
> >
> > The error is generated for the second line above complaining
> > that the object (foo) is not a class (it is indeed).
> >
> > This code does compile:
> >
> > Foo *foo(filename);
> > int count = foo->get_count();
> > delete foo;
> >
> > Why does the first version fail and the second succeed?
> >
> > [Visual C++ .NET Version 7.0.9466]
> >
>


Thanks for replying Robert.

I am using standard C++ syntax and no /clr.

I too tried to reproduce the problem with a simple test case
as you did, but the test case does not exhibit the problem.

As Craig Powers indicated, this appears to be a problem in
which a function is declared instead of a CTOR being called.
The "Foo" class was ported from UNIX systems. The CTOR takes
a std::string and the various compilers I use on these different
systems silently construct a string from a char* argument.
Even on these UNIX systems, if I explicitly construct a string
in the call to the Foo CTOR:

Foo foo(string(filename));

then they too exhibit the function declaration behavior.
But at least they allow this:

Foo foo((string(filename)));


It is odd that this declares a function:

> > Foo foo(string(filename));

and this does not:

> > Foo *foo(string(filename));

[Please see my second post on 2003-04-07 for more detail.]

I would be glad to provide more info on project settings
if needed.

Craig Powers

unread,
Apr 9, 2003, 11:45:41 AM4/9/03
to
Mike Loftus wrote:
>
> It is odd that this declares a function:
>
> > > Foo foo(string(filename));
>
> and this does not:
>
> > > Foo *foo(string(filename));

Just looking at it, I would expect that the second would declare a
function returning a Foo*.

Larry Brasfield

unread,
Apr 9, 2003, 1:12:50 PM4/9/03
to
In article <3E944025...@hal-pc.org>,
Craig Powers (eni...@hal-pc.org) says...

> Mike Loftus wrote:
> >
> > It is odd that this declares a function:
> >
> > > > Foo foo(string(filename));
> >
> > and this does not:
> >
> > > > Foo *foo(string(filename));
>
> Just looking at it, I would expect that the second would declare a
> function returning a Foo*.

Would you not, then, also expect the first to
declare a function returning a Foo?

I agree with the OP's claim that it is odd.
There is more going on here than his initial
post indicates. Time for a real code sample!

--
-Larry Brasfield
(address munged, s/sn/h/ to reply)

Mike Loftus

unread,
Apr 9, 2003, 1:35:58 PM4/9/03
to
"Craig Powers" <eni...@hal-pc.org> wrote in message
news:3E944025...@hal-pc.org...

> Mike Loftus wrote:
> >
> > It is odd that this declares a function:
> >
> > > > Foo foo(string(filename));
> >
> > and this does not:
> >
> > > > Foo *foo(string(filename));
>
> Just looking at it, I would expect that the second would declare a
> function returning a Foo*.
>

Please se my original post - the
compiler treats them differently.

Mike Loftus

unread,
Apr 9, 2003, 1:42:28 PM4/9/03
to
"Larry Brasfield" <larry_b...@snotmail.com> wrote in message
news:MPG.18fdf46eb...@msnews.microsoft.com...

Can't post real code. But I will try to
generate a sample that does the same.

Jeff Peil [MSFT]

unread,
Apr 9, 2003, 2:36:03 PM4/9/03
to
"Mike Loftus" <mlof...@ford.error.com> wrote in message
news:b71llu$id...@eccws12.dearborn.ford.com

> "Craig Powers" <eni...@hal-pc.org> wrote in message
> news:3E944025...@hal-pc.org...
>> Mike Loftus wrote:
>>>
>>> It is odd that this declares a function:
>>>
>>>>> Foo foo(string(filename));
>>>
>>> and this does not:
>>>
>>>>> Foo *foo(string(filename));
>>
>> Just looking at it, I would expect that the second would declare a
>> function returning a Foo*.
>>
>
> Please se my original post - the
> compiler treats them differently.

Did you really write "Foo *foo(string(filename));"?


This seems unlikely as the compiler would have seen this as a function
returning a Foo* (and with the ambiguity removed, I doubt it would work as
there shouldn't be a UDC from a std::string to a Foo*.) Did you really
write something closer to "Foo* foo = new Foo(string(filename));"?

--
Jeff Peil

Craig Powers

unread,
Apr 9, 2003, 3:09:13 PM4/9/03
to
Larry Brasfield wrote:
>
> In article <3E944025...@hal-pc.org>,
> Craig Powers (eni...@hal-pc.org) says...
> > Mike Loftus wrote:
> > >
> > > It is odd that this declares a function:
> > >
> > > > > Foo foo(string(filename));
> > >
> > > and this does not:
> > >
> > > > > Foo *foo(string(filename));
> >
> > Just looking at it, I would expect that the second would declare a
> > function returning a Foo*.
>
> Would you not, then, also expect the first to
> declare a function returning a Foo?

Indeed I would. And in fact, it does. The oddity that is observed is
that (according to the post to which I replied), VC sees the first as
a function declaration (as I would expect) but not the second.

> Time for a real code sample!

Agreed.

Mike Loftus

unread,
Apr 9, 2003, 3:12:26 PM4/9/03
to
"Larry Brasfield" <larry_b...@snotmail.com> wrote in message
news:MPG.18fdf46eb...@msnews.microsoft.com...

I have created a sample version of "Foo" (replacing
proprietary classes with ints & strings and changing
all names) but with this sample code, the following
statements:

Foo foo(string(filename));
Foo *foo(string(filename));

are both treated as function declarations. I'll
continue to prod the sample into misbehaving.

If anyone is interested in what the sample
class looks like, here's the code (sorry if the
formatting gets whacked by word-wrap):

//--------------------------------------------------
#ifndef FOO_H
#define FOO_H

#include <map>
#include <string>
#include <vector>
using namespace std;

//=================================================
// Foo
//=================================================
class Foo
{
friend ostream &operator<<(ostream &os,
Foo &foo);

public:
Foo(string const &filename);
~Foo();

//---------------------------------------
// FooNest1
//---------------------------------------
class FooNest1
{
friend istream &operator>>(istream &is,
FooNest1 &fn);
friend ostream &operator<<(ostream &os,
FooNest1 const &fn);

public:
FooNest1();
FooNest1(map<int, string> const &stuff);
~FooNest1();

void add_item(int const &id,
string const &name);

int get_count() const;
vector<int> get_ids() const;
vector<string> get_names() const;

protected:
map<int, vector<string> > store;
map<int, vector<string> >::const_iterator mutable store_iter;
};

//---------------------------------------
// FooNest2
//---------------------------------------
class FooNest2
{
friend istream &operator>>(istream &is,
FooNest2 &fn);
friend ostream &operator<<(ostream &os,
FooNest2 const &fn);
public:
FooNest2();
~FooNest2();

string get_name() const;
map<int, string> get_defs() const;

protected:
string name;
map<int, string> defs;
map<int, string>::const_iterator mutable def_iter;
};

vector<int> get_ids() const;
vector<string> get_names() const;
vector<float> get_stuff(int const &id,
unsigned __int64 const &x) const;

FooNest1 get_foo_nest1() const;
vector<FooNest2> get_foo_nest2(int const &id) const;

protected:
map<int, string> store1;
map<int, string>::const_iterator mutable mi;
vector<string> store2;
vector<string>::iterator mutable vi;

map<int, vector<FooNest2> > foo_nest2_store;
map<int, vector<FooNest2> >::const_iterator mutable fn2si;
};

#endif // FOO_H

Tanveer Gani [MSFT]

unread,
Apr 10, 2003, 2:45:23 PM4/10/03
to

--------------------
> Message-ID: <3E91EF4F...@hal-pc.org>
> Date: Mon, 07 Apr 2003 16:36:15 -0500

Craig is right. In the code example in the original post, my guess is that
"filename" is a type name.

But it gets worse. E.g.,

struct B {
B();
};


B b(B());

doesn't do the obvious, i.e., initialize "b" with a temporary of type "B".
It's really a function declaration of a function "b" returning "B" and
taking a function pointer of the type "B (*)(void)" as a parameter.

One way to catch these errors in local scopes is to remove the object
reference. For example, if you just said

{
Foo foo(filename);
}

and didn't use foo.something(), etc. you'd get a warning about the unused
function decl "foo" which could give you some clue as to what's wrong.

BTW, this is all correct behaviour - the ISO Standard requires us to always
disambiguate in favour of a declaration.


--
Tanveer Gani, Visual C++ Team

Mike Loftus

unread,
Apr 10, 2003, 11:11:43 PM4/10/03
to
"Jeff Peil [MSFT]" <jp...@bigfoot.com> wrote in message
news:esc3Ids$CHA....@TK2MSFTNGP10.phx.gbl...

>
> Did you really write "Foo *foo(string(filename));"?
>

Yes - I'd swear on a stack of ... pancakes. ;)

I left the statement in the code (commented-out)
for about a day before deleting it. Since
noticing the oddity, the class "Foo", the four
classes it is built-upon, and the application
using "Foo" have all changed. I've attempted to
roll-back to how (I think) things were when I
experienced this behavior, without luck of
repeating it.

Mike Loftus

unread,
Apr 10, 2003, 11:26:00 PM4/10/03
to
"Tanveer Gani [MSFT]" <tg...@online.microsoft.com> wrote in message
news:QupicF5$CHA...@cpmsftngxa06.phx.gbl...

>
> One way to catch these errors in local scopes is to remove the object
> reference. For example, if you just said
>
> {
> Foo foo(filename);
> }
>
> and didn't use foo.something(), etc. you'd get a warning about the unused
> function decl "foo" which could give you some clue as to what's wrong.

As I am in the process of learning the MSVC project
development environment, that is exactly how I tested
to see if my external libraries and headers would be
found and correctly linked into the app - I simply
attempted to instantiate a "Foo" - realizing that the
compiler may not actually incorporate the statement
since "foo" was never referenced. Although I may
be wrong, I do not recall any such warning as you've
mentioned.

> BTW, this is all correct behaviour - the ISO Standard requires us to
always
> disambiguate in favour of a declaration.
>
>

Thank you Tanveer.

Tanveer Gani [MSFT]

unread,
Apr 11, 2003, 1:14:34 PM4/11/03
to

--------------------
> From: "Mike Loftus" <con...@loftusoft.error.com>
> Newsgroups: microsoft.public.dotnet.languages.vc
> References: <b6s4i9$la...@eccws12.dearborn.ford.com>
<b6sk4j$pr...@eccws12.dearborn.ford.com> <

I'm talking about this:

x.cpp(5) : warning C4930: 'Foo foo(int_t)': prototyped function not called
(was
a variable definition intended?)

This is a level 1 warning and is present in both VS 2002 and VS 2003.

0 new messages