a pair of questions

A

Alexander Korovyev

Hello,

1) Should a standard compliant compiler accept the following code:

void Foo() { /* ... */ }
class Foo { /* ... */ };

int main()
{
Foo();
return 0;
}

If yes, what do you think the language allows it for? By the way, can
you predict what the program will do -- construct the object or call
the function?

2) Can you tell what exactly this short program will print?

#include<iostream>
using std::cout;

class MyClass {
public:
MyClass() : i_(2) {}
MyClass(const MyClass& obj) { i_ *= obj.i_; }
~MyClass() { cout << i_ << std::endl; }
private:
int i_;
};

int main()
{
MyClass( MyClass() );
return 0;
}

-Alexander
 
A

Alf P. Steinbach

1) Should a standard compliant compiler accept the following code:

void Foo() { /* ... */ }
class Foo { /* ... */ };

int main()
{
Foo();
return 0;
}

If yes, what do you think the language allows it for? By the way, can
you predict what the program will do -- construct the object or call
the function?

If this was a real question the advice would be to use
different names.

But as a HOMEWORK PROBLEM the advice is to (1) check your
textbook, and (2) check the standard. Find the relevant
pages. In your answer, don't answer just yes or no, and
don't just quote an authoritative source, but also include
the reasoning _why_ it is like it is.


2) Can you tell what exactly this short program will print?

#include<iostream>
using std::cout;

class MyClass {
public:
MyClass() : i_(2) {}
MyClass(const MyClass& obj) { i_ *= obj.i_; }
~MyClass() { cout << i_ << std::endl; }
private:
int i_;
};

int main()
{
MyClass( MyClass() );
return 0;
}

Why don't you try to compile it, and if it compiles, run it,
and if it runs and you don't understand it, trying it in
a debugger?

Note: that a program compiles with one specific compiler and
compiler options doesn't mean it has defined behavior according
to the standard, but either way you know a lot more.

But you didn't even try, so, are you stupid?
 
M

MiniDisc_2k2

Alexander Korovyev said:
Hello,

1) Should a standard compliant compiler accept the following code:

void Foo() { /* ... */ }
class Foo { /* ... */ };

int main()
{
Foo();
return 0;
}

My compiler, VC++6, compiles it fine. Of course, VC++ is known for its
non-standard conventions, but it seems like it is perfectly legal, and
should be.
If yes, what do you think the language allows it for?

It's the same reason you could use Foo() and foo() to mean two different
functions. It just gives you more names you could use. As it will always be
unambiguous to what you mean, it's ok to do this.
By the way, can
you predict what the program will do -- construct the object or call
the function?

I just said it's always unambiguous. Thus, reading into your code a bit will
tell you. It could not possibly be constructing the object as there is no
variable there, so there is nothing to construct. It is, therefore, calling
the function. IIRC, the defauly constructor, in this case, would have to be
called as Foo::Foo(), to make it unambiguous.
2) Can you tell what exactly this short program will print?

#include<iostream>
using std::cout;

class MyClass {
public:
MyClass() : i_(2) {}
MyClass(const MyClass& obj) { i_ *= obj.i_; }
~MyClass() { cout << i_ << std::endl; }
private:
int i_;
};

int main()
{
MyClass( MyClass() );
return 0;
}

-Alexander

Well my compiler prints 2. IMHO, you're lucky, though. It appears to me
that:

1) the first constructor that's called makes its i_ 2.
2) the copy constructor then takes its i_ and multiplies it by 2. As its i_
is undefined, it appears that this code is also undefined.

Then again, here's another way of looking at it:

MyClass(MyClass());

As the constructor(s) don't return a value, this is the same as saying

MyClass(void);

Which would be the same as saying

MyClass();

Which would make i_ 2.


Then again, as two constructors were called, shouldn't there be two 2s on
output? I only saw one. Perhaps the compiler optimized it out??

That's really confusing, but is this a homework assignment or something? Are
you curious? This seems to have no practical purpose to me...
 
G

Gianni Mariani

MiniDisc_2k2 said:
Then again, here's another way of looking at it:

MyClass(MyClass());

As the constructor(s) don't return a value, this is the same as saying

MyClass(void);

Which would be the same as saying

MyClass();

Which would make i_ 2.


Then again, as two constructors were called, shouldn't there be two 2s on
output? I only saw one. Perhaps the compiler optimized it out??

That's really confusing, but is this a homework assignment or something? Are
you curious? This seems to have no practical purpose to me...

Then g++ thinks that "MyClass( MyClass() );" declares a function MyClass
that returns a MyClass and prints nothing at all.

int main()
{
MyClass( MyClass() ); // declare function MyClass

::MyClass xx( MyClass() ); // call function MyClass

return 0;
}

And who thought this was a good idea ?
 
V

Victor Bazarov

Constructors return objects. They don't have a return value
types in a regular sense because they cannot be called.
Then g++ thinks that "MyClass( MyClass() );" declares a function MyClass
that returns a MyClass and prints nothing at all.

int main()
{
MyClass( MyClass() ); // declare function MyClass

There are no implicit return types in C++. If 'MyClass hasn't
been defined, the statement above is a syntax error. If g++ allows
it, g++ is simply wrong, then.

OTOH, if 'MyClass' is a type-id, then it's a creation of
a temporary from another temporary. Both are discared at ';'.
 
G

Gianni Mariani

Victor said:
There are no implicit return types in C++. If 'MyClass hasn't
been defined, the statement above is a syntax error. If g++ allows
it, g++ is simply wrong, then.

OTOH, if 'MyClass' is a type-id, then it's a creation of
a temporary from another temporary. Both are discared at ';'.

I'm pretty sure you missed the point. I HAVE NO IDEA if this is correct
C++ but the gcc 3.3 compiler recognizes this:


MyClass( MyClass() );

as a declaration of a function called "MyClass" taking no parameters and
returning a MyClass object.

If you then try to calling it like so:

::MyClass xx( MyClass() );

It will actually call function "MyClass()".


Hey, what happened to my kill file.

Go figure.
 
V

Victor Bazarov

Gianni Mariani said:
I'm pretty sure you missed the point. I HAVE NO IDEA if this is correct
C++ but the gcc 3.3 compiler recognizes this:


MyClass( MyClass() );

as a declaration of a function called "MyClass" taking no parameters and
returning a MyClass object.

I probably missed the point. And, yes, it's not correct C++.

Victor
 
S

Shane Beasley

1) Should a standard compliant compiler accept the following code:

void Foo() { /* ... */ }
class Foo { /* ... */ };

int main()
{
Foo();
return 0;
}

If anything in this world can answer your question correctly, this is it:

If yes, what do you think the language allows it for?

C compatibility. The following is the POSIX way for getting the size of a file:

struct stat st;
if (stat(filename, &st)) printf("%d\n", st.st_size);

(Microsoft calls them "_stat" and "struct _stat", respectively.)
By the way, can you predict what the program will do -- construct the
object or call the function?

Yes, I can. You can, too, if you read carefully.
2) Can you tell what exactly this short program will print?

#include<iostream>
using std::cout;

class MyClass {
public:
MyClass() : i_(2) {}
MyClass(const MyClass& obj) { i_ *= obj.i_; }
~MyClass() { cout << i_ << std::endl; }
private:
int i_;
};

int main()
{
MyClass( MyClass() );
return 0;
}

No, nor can anyone else.

- Shane
 
A

Alexander Korovyev

MiniDisc_2k2 said:
Then again, as two constructors were called, shouldn't there be two 2s on
output? I only saw one. Perhaps the compiler optimized it out??

That's really confusing, but is this a homework assignment or something? Are
you curious? This seems to have no practical purpose to me...

The question arose from reading Andrei Alexandrescu's "Modern C++
Design". In section 2.1 he describes a technique of compile-time
assertion checking:

template<bool> struct CompileTimeChecker
{
CompileTimeChecker(…);
};
template<> struct CompileTimeChecker<false> {};
#define STATIC_CHECK(expr, msg) \
{\
class ERROR_##msg{}; \
(void)sizeof(CompileTimeChecker<(expr) != 0>(ERROR_##msg())); \
}

where CompileTimeChecker<(expr) != 0>(ERROR_##msg()) is intended by
the author to evaluate in an object. Believe it or not, but the latest
Microsoft compiler interprets it as a function pointer declaration!
Likewise, MyClass(MyClass()) line in question 2) of my posting is
interpreted not as a successive construction of two automatic objects,
but as the MyClass (*MyClass)() declaration. This unfortunate
situation IMHO could not be possible if C++ did not effectively add
extra headache by admitting the collision described in question 1) (or
doesn't it really admit so?). So the reason I asked was to clarify
whether it was Mr. Alexandrescu's mistake due to the too much
complexity of C++ syntax or the shortcoming of my compilers.

-Alexander
 
A

Alexander Korovyev

(e-mail address removed) (Alexander Korovyev) wrote in message
[skipped]
2) Can you tell what exactly this short program will print?

#include<iostream>
using std::cout;

class MyClass {
public:
MyClass() : i_(2) {}
MyClass(const MyClass& obj) { i_ *= obj.i_; }
~MyClass() { cout << i_ << std::endl; }
private:
int i_;
};

int main()
{
MyClass( MyClass() );
return 0;
}

No, nor can anyone else.

Well, it is clear there are at most only two possibilities -- the
program output is either undefined or is empty. Is there really a set
of C++ rules implying that
MyClass( MyClass() );
can never be a function pointer declaration?

-Alexander
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,682
Members
48,796
Latest member
Greg L.

Latest Threads

Top