pointer to a function?

F

Fraser Ross

class S {
public:
struct RValue {
RValue() {}
};
struct FValue {
FValue() {}
};
explicit S(RValue) {}
explicit S(FValue) {}
};

void P(S) {
}

int main()
{
S const d((S::RValue()));

P(d);
return 0;
}


It appears to me that the object d is passed a pointer to a function
with no parameters and returns an S::RValue. The Codegear compiler
agrees with me although the Comeau one doesn't. I don't think it will
compile without making a named argument for d unless anyone knows
otherwise?

Fraser.
 
F

Fraser Ross

It appears to me that the object d is passed a pointer to a function
No, it's not a pointer to a function. It's a temporary object of type
S::RValue, default-constructed. The extra set of parentheses around
the expression 'S::RValue()' makes it an expression, not a
declaration. Drop the extra parens, and Comeau will complain.

I am talking about S::RValue(). Its a pointer to a function as I said.
I can't put parentheses around an argument because there isn't one.

Fraser.
 
A

Alf P. Steinbach

* Fraser Ross:
I am talking about S::RValue(). Its a pointer to a function as I said.
I can't put parentheses around an argument because there isn't one.

It is as Victor says.

Basta.

Or in other words, you're simply wrong about this.


Cheers & hth.,

- Alf
 
F

Fraser Ross

Alf P. Steinbach said:
* Fraser Ross:

It is as Victor says.

Basta.

Or in other words, you're simply wrong about this.


The extra parentheses should make d an object instead of a pointer to a
function. S::RValue() is an unnamed pointer to a function because I
can't write S::RValue(()). S does not have a constructor that takes a
pointer to a function. Codegear correctly sees S::RValue() as a pointer
to a function.

Fraser.
 
F

Fraser Ross

"Jeff Schwab"
You didn't just write S::RValue(), you wrote ((S::RValue())). Those
are the extra parentheses in question. It's not a function-pointer,
it's a default-constructed S::RValue. Providing the extra
parentheses, as a work-around meant specifically to avoid the
function-pointer interpretation, is a well-known syntactic
inconvenience.

The extra parentheses should make d an object instead of a pointer to a
function. I used it there and I know its a well known idiom.
S::RValue() is an unnamed pointer to a function because I can't write
S::RValue(()). Extra parentheses around an argument doesn't change one
from a pointer to a function, to an object. The argument is still a
pointer to a function.


Fraser.
 
F

Fraser Ross

My example has code similar to this from Effective STL:
int g(double ());

The book says that the parameter double() is a pointer to a function.
According to the first thing you said Victor its a double value 0.
"It's a temporary object of type
S::RValue, default-constructed."

Fraser.
 
F

Fraser Ross

Just to make sure, we're talking about

T1 name( T2() );

versus

T1 name( ( T2() ) );

That's what you did, and your compiler ("Codegear") still thinks that
the statement is a declaration for 'name' as a function?

I don't think so but the argument in the second line is parsed as a
pointer to a function as it would be if name was a function.

Noboby suggest that you do. If you need a work-around for your
compiler's bug, try adding an argument to the 'RValue' and 'GValue'
constructor, like an int, and pass 0:

S const d(S::RValue(0));
Possible.


this should shut it up. Or simply switch to templates, so that your
declaration looks like

S<S::RValue> const d;

I want only one type S.


This fails to compile:
int g((double ()));

Its the same bug and a much shorter example.

Fraser.
 
T

Thomas J. Gritzan

Fraser said:
I don't think so but the argument in the second line is parsed as a
pointer to a function as it would be if name was a function.

How do you know that (T2()) is parsed as a function pointer?

I just tried to compile
int g((double ()));
in CodeGear C++ Builder and the error message only tells "Expression
syntax", which is a universal error when an expression can't be parsed.
This fails to compile:
int g((double ()));

Its the same bug and a much shorter example.

Yes. It seems to be a bug in C++ Builder.
 
J

Juha Nieminen

Fraser said:
My example has code similar to this from Effective STL:
int g(double ());

The book says that the parameter double() is a pointer to a function.

I'm not sure I agree with that terminology. If we had this:

double(*funcPtr)();

then we can say that "funcPtr is a pointer to a function". That's
because "funcPtr" is an actual variable, an actual pointer.

With "int g(double());" you are only declaring a function named g, as
a function taking a function pointer and returning an int. You are not
actually declaring an actual function pointer anywhere. Thus I'm not
sure I agree with saying "double() is a pointer to a function". It's not
a pointer, it's only a declaration.

If you said "in this expression double() declares a function pointer
type" then it would be, IMO, more accurate.
My example has code similar to this from Effective STL:
int g(double ());

Your example was maybe similar on a quick glance, but the extra
parentheses in your example make a whole lot of a difference. They make
your code to have a completely different meaning than that.

"int g(double());" and "int g((double()));" are two completely
different expressions which have absolutely nothing in common (except
for the name 'g'). The first declares a function, the second
instantiates a variable of type int and initializes it to the default
initialization value of double.

Just because those two expressions may look similar doesn't mean they
actually are.
 
J

James Kanze

I am talking about S::RValue(). Its a pointer to a function
as I said.

Not in your original code. The token sequence "S::RValue()" can
be either a type specification of a pointer to a function, or an
expression which creates a temporary value initialized instance
of an S::RValue. Which one depends on the context---if a type
specification is legal in the context where the token sequence
occurs, it will be the type specification; otherwise, it creates
the temporary.

In the code you posted, a type specification is not legal in the
context where the token sequence occurs.
I can't put parentheses around an argument because there isn't
one.

The "extra parens" Victor was talking about were those around
the expression (S::RValue()) in your code:

S const d( S::RValue() ) ;
// type specification legal here, results in the
// declaration of a function returning an S const, and
// taking a pointer to a function returning an S::RValue
// as argument.
S const d( ( S::RValue() ) ) ;
// type specification NOT legal in parentheses, so
// declaration of a variable of type S const,
// initialized by calling a constructor with the
// temporary object created by S::RValue().

Since the code you posted had the extra parentheses, there are
no pointers to functions.
 
J

James Kanze

"Jeff Schwab"
The extra parentheses should make d an object instead of a
pointer to a function. I used it there and I know its a well
known idiom. S::RValue() is an unnamed pointer to a function

There is NO context where S::RValue() is an unnamed pointer to a
function. S::RValue() can be a type expression, with type
function (which will decay to pointer to function in certain
contexts), or it can be a normal expression, creating a
temporary S::RValue(). The first will only occur in contexts
where type expressions are legal. The extra parentheses around
this expression in your code create a context where a type
expression isn't legal.
because I can't write S::RValue(()). Extra parentheses around
an argument doesn't change one from a pointer to a function,
to an object. The argument is still a pointer to a function.

Extra parentheses around an expression cannot change the type of
a value. But that's not an issue: as a value "S::RValue()" can
only be a temporary of type S::RValue, not a pointer to a
function. The issue is whether the token sequence can be
interpreted as a type expression. And in this case, the extra
parentheses mean that it can't. (It's possible to construct
cases where the reverse is true; in:
S::RValue() * p
"S::RValue()" must be a value, but in:
(S::RValue()) * p
it can be a type expression: the first multiplies the value
S::RValue() by p (which will cause an error if the types in
question don't support multiplication); the second is a C style
cast expression, which converts the results of dereferencing p
into a pointer to a function.

Such horrors are the price we pay for deriving from C.
 

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
473,770
Messages
2,569,584
Members
45,077
Latest member
SangMoor21

Latest Threads

Top