 |
BorlandTalk.com Borland discussion newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Leroy Casterline Guest
|
Posted: Wed Dec 14, 2005 9:39 pm Post subject: Please help me understand this error |
|
|
I must be doing something wrong, but I need someone smarter than I to
explain this:
[C++ Error] Main.cpp(2775): E2285 Could not find a match for
'TUSB::TUSB(void (_fastcall * (_closure )(int))(int))'
Why does BCB 6 think SwitchChangeCallback has this signature?
Line in error:
USB = new TUSB(&SwitchChangeCallback);
In Main.cpp:
void __fastcall TFormMain::SwitchChangeCallback(int NewSwitchPos)
{
}
In Main.h (in TFormMain class definition):
TUSB *USB;
void __fastcall SwitchChangeCallback(int);
In USB.h:
typedef void __fastcall (__closure *SwitchMonitorCallback)(int);
In TUSB class definition:
__fastcall TUSB(SwitchMonitorCallback);
In USB.cpp:
__fastcall TUSB::TUSB(SwitchMonitorCallback SwitchCallback)
|
|
| Back to top |
|
 |
Remy Lebeau (TeamB) Guest
|
Posted: Wed Dec 14, 2005 11:03 pm Post subject: Re: Please help me understand this error |
|
|
"Leroy Casterline" <casterle (AT) ccltd (DOT) com> wrote
| Quote: | [C++ Error] Main.cpp(2775): E2285 Could not find a match for
'TUSB::TUSB(void (_fastcall * (_closure )(int))(int))'
|
Using the exact code you have show, I cannot reproduce that error in my copy
of BCB6. Please show a more complete code snippet.
| Quote: | Why does BCB 6 think SwitchChangeCallback has this signature?
|
Because it actually does.
Gambit
|
|
| Back to top |
|
 |
Leroy Casterline Guest
|
Posted: Wed Dec 14, 2005 11:50 pm Post subject: Re: Please help me understand this error |
|
|
On Wed, 14 Dec 2005 15:03:26 -0800, "Remy Lebeau (TeamB)"
<no.spam (AT) no (DOT) spam.com> wrote:
Thanks for taking a look, Remy.
| Quote: | [C++ Error] Main.cpp(2775): E2285 Could not find a match for
'TUSB::TUSB(void (_fastcall * (_closure )(int))(int))'
Using the exact code you have show, I cannot reproduce that error in my copy
of BCB6. Please show a more complete code snippet.
|
See below.
| Quote: | Why does BCB 6 think SwitchChangeCallback has this signature?
Because it actually does.
|
Where does the extra int come from?
From Main.cpp:
//--------------------------------------------------------------------------------------------------
// OpenIODevice - try to open USB device, return true if successful
//--------------------------------------------------------------------------------------------------
bool __fastcall TFormMain::OpenIODevice(void)
{
// try to open USB device, set program state dependent on result
Data->USBDeviceOpen = true;
try {
PanelNoUSB->Visible = false;
USB = new TUSB(&SwitchChangeCallback);
} catch(...) {
PanelNoUSB->Visible = true;
Data->USBDeviceOpen = false;
ShowMessage("The evaluation board was not found on a USB
port.");
}
return Data->USBDeviceOpen;
}
//--------------------------------------------------------------------------------------------------
// SwitchChangeCallback - called from switch monitor thread when
hardware switch changed
//--------------------------------------------------------------------------------------------------
void __fastcall TFormMain::SwitchChangeCallback(int NewSwitchPos)
{
}
From Main.h:
//-----------------------------------------------------------------------------------------------
// TFromMain
//-----------------------------------------------------------------------------------------------
class TFormMain : public TForm {
private:
void __fastcall SwitchChangeCallback (int);
bool __fastcall OpenIODevice (void);
public:
__fastcall TFormMain(TComponent* Owner);
__fastcall ~TFormMain(void);
};
From USB.cpp:
//--------------------------------------------------------------------------------------------------
// constructor
//--------------------------------------------------------------------------------------------------
__fastcall TUSB::TUSB(SwitchMonitorCallback SwitchCallback)
{
try {
SwitchMonitor = new TSwitchMonitor(this, SwitchCallback,
GetSwitchValue(), false);
} catch(...) {
AnsiString Msg = "Can't create SwitchMonitorThread.";
CodeSiteWrap(CodeSiteLog->SendError(Msg));
CodeSiteWrap(FormCodeSite->DestroyCodeSiteObject(CodeSiteLog));
throw Exception(Msg);
}
}
From USB.h:
//-----------------------------------------------------------------------------------------------
// TUSB
//-----------------------------------------------------------------------------------------------
class TUSB : public TObject {
public:
__fastcall TUSB (SwitchMonitorCallback);
__fastcall ~TUSB (void);
};
From SwitchMonitorThread.cpp:
//--------------------------------------------------------------------------------------------------
// constructor
//--------------------------------------------------------------------------------------------------
__fastcall TSwitchMonitor::TSwitchMonitor(TUSB *USBPort,
SwitchMonitorCallback Callback, int SwitchPos, bool CreateSuspended) :
TThread(CreateSuspended)
{
USB = USBPort;
SwitchCallback = Callback;
CurrentSwitchPos = SwitchPos;
}
From SwitchMonitorThread.h:
typedef void __fastcall (__closure *SwitchMonitorCallback)(int);
//-----------------------------------------------------------------------------------------------
// TSwitchMonitor
//-----------------------------------------------------------------------------------------------
class TSwitchMonitor : public TThread {
public:
__fastcall TSwitchMonitor(TUSB *, SwitchMonitorCallback, int,
bool CreateSuspended);
};
|
|
| Back to top |
|
 |
Remy Lebeau (TeamB) Guest
|
Posted: Thu Dec 15, 2005 12:34 am Post subject: Re: Please help me understand this error |
|
|
"Leroy Casterline" <casterle (AT) ccltd (DOT) com> wrote
| Quote: | Where does the extra int come from?
|
There isn't an extra int. Look more closely at the paranthesis that are
used. There is only 1 actual int parameter. What you think is an extra int
is not actually an extra parameter. It is attached to the __closure. For
whatever reason, Borland duplicates parameter lists when displaying
__closure signatures. That does not mean that are are actual extra
parameters present.
Once again, using the exact code you have shown, I cannot duplicate the
error. It compiles and runs fine for me (once I fill in the missing pieces
that you did not show, that is).
Do you have all of the updates installed for BCB6?
Gambit
|
|
| Back to top |
|
 |
Leroy Casterline Guest
|
Posted: Thu Dec 15, 2005 2:23 am Post subject: Re: Please help me understand this error |
|
|
On Wed, 14 Dec 2005 16:34:49 -0800, "Remy Lebeau (TeamB)"
<no.spam (AT) no (DOT) spam.com> wrote:
| Quote: | There isn't an extra int. Look more closely at the paranthesis that are
used. There is only 1 actual int parameter. What you think is an extra int
is not actually an extra parameter. It is attached to the __closure. For
whatever reason, Borland duplicates parameter lists when displaying
__closure signatures. That does not mean that are are actual extra
parameters present.
|
OK, thanks for the explanation.
| Quote: | Once again, using the exact code you have shown, I cannot duplicate the
error. It compiles and runs fine for me (once I fill in the missing pieces
that you did not show, that is).
Do you have all of the updates installed for BCB6?
|
Yes. I guess I'm going to have to start chopping things out of my
project and see what's causing this.
Thanks for taking time to give this a try.
|
|
| Back to top |
|
 |
Leroy Casterline Guest
|
Posted: Thu Dec 15, 2005 6:03 pm Post subject: Re: Please help me understand this error |
|
|
On Wed, 14 Dec 2005 16:34:49 -0800, "Remy Lebeau (TeamB)"
<no.spam (AT) no (DOT) spam.com> wrote:
OK, Remy, I've broken this down to a simple test case which I've
uploaded to the attachments group (C++ test project for Remy).
The same error is still occuring, but it has moved from Main.cpp to
USB.cpp:
SwitchMonitor = new TSwitchMonitor(&GetSwitchValue,
&SwitchCallback, GetSwitchValue(), false);
The 2nd parameter is the one that creates the error.
Could you please try to compile my test project and see if you get the
error?
|
|
| Back to top |
|
 |
Remy Lebeau (TeamB) Guest
|
Posted: Thu Dec 15, 2005 6:25 pm Post subject: Re: Please help me understand this error |
|
|
"Leroy Casterline" <casterle (AT) ccltd (DOT) com> wrote
| Quote: | SwitchMonitor = new TSwitchMonitor(&GetSwitchValue,
&SwitchCallback, GetSwitchValue(), false);
The 2nd parameter is the one that creates the error.
|
You need to remove the '&' from the second parameter. You use the '&' only
when specifying an actual method, not a pointer to a method. Since you are
not passing an actual method directly like you are in the first parameter,
and since 'SwitchCallback' is a parameter of the TUSB constructor, you can
pass it to TSwitchMonitor's constructor as-is without using the '&', ie:
SwitchMonitor = new TSwitchMonitor(&GetSwitchValue, SwitchCallback,
GetSwitchValue(), false);
Gambit
|
|
| Back to top |
|
 |
Remy Lebeau (TeamB) Guest
|
Posted: Thu Dec 15, 2005 6:29 pm Post subject: Re: Please help me understand this error |
|
|
"Leroy Casterline" <casterle (AT) ccltd (DOT) com> wrote
| Quote: | SwitchMonitor = new TSwitchMonitor(&GetSwitchValue,
&SwitchCallback, GetSwitchValue(), false);
The 2nd parameter is the one that creates the error.
|
If you look very closely at the error message, you will see an extra '*' in
the (__closure) of the second parameter:
void (_fastcall * (_closure *)(int) *)(int)
If you look at the first parameter, you will not see that:
int (_fastcall * (_closure )())(),
That extra '*' means that your second parameter is passing a *pointer to* a
pointer to a method. But the parameter expects just a single pointer to a
method directly instead. Your use of the '&' on the second parameter is
creating an extra pointer that you do not need.
Gambit
|
|
| Back to top |
|
 |
Leroy Casterline Guest
|
Posted: Thu Dec 15, 2005 11:00 pm Post subject: Re: Please help me understand this error |
|
|
On Thu, 15 Dec 2005 10:29:10 -0800, "Remy Lebeau (TeamB)"
<no.spam (AT) no (DOT) spam.com> wrote:
| Quote: | If you look very closely at the error message, you will see an extra '*' in
the (__closure) of the second parameter:
void (_fastcall * (_closure *)(int) *)(int)
|
Thanks, I didn't notice the extra '*', but I think a more basic
problem is that I don't know how to read this.
The original signature that couldn't be matched is:
void (_fastcall * (_closure )(int))(int)
Reading this using the right/left rule:
1) Start at the identifier which would, I guess, be to the right of
the _closure, we can't go right because of the paren, so going left we
find _closure.
This is a _closure.
2) Outside the 1st parens and now in the 2nd parens, to the right we
find (int).
This is a _closure function taking an int parameter.
3) Still inside the 2nd level of parens, to the right we find a *.
This is a _closure function taking an int parameter returning a
pointer.
4) Still inside the 2nd level of parens, to the right we find
_fastcall.
This is a _closure function taking an int parameter returning a
pointer to a _fastcall.
5) Outside the parens, to the right we find (int)
This is a _closure function taking an int parameter returning a
pointer to a _fastcall function taking an int parameter.
6) Finally to the left we find a void.
This is a _closure function taking an int parameter returning a
pointer to a _fastcall function taking an int parameter and returning
void.
So in the error that started this thread, the compiler was looking for
the TUSB constructor to have an argument that was a _closure function
taking an int parameter returning a pointer to a _fastcall function
taking an int parameter and returning void.
But the TUSB constructor takes:
typedef void __fastcall (__closure *SwitchMonitorCallback)(int);
in which SwitchMonitorCallback is a pointer to a closure taking an int
parameter and returning a void. See NOTE 1 below.
So clearly the expectations of the compiler differ from the
constructor argument type declared in the code.
This seems like a compiler bug.
Now, continuing with the error message that was generated by my
misapplication of & to the function pointer:
void (_fastcall * (_closure *)(int) *)(int)
Again using the right/left rule and assuming the identifier would be
to the right of the * in the _closure part of the definition):
1) We can't go right 'cause of the paren, so we go left and find *.
This is a pointer.
2) We go left again and find _closure.
This is a pointer to a closure.
3) Outside the 1st parens, we go right and find (int).
This is a pointer to a _closure function taking an int parameter.
4) Still inside the 2nd parens, we go left and find *.
This is a pointer to a _closure function taking an in parameter and
returning a pointer.
5) Still inside the 2nd parens we go right and find *.
I don't know how to interpret this using the right/left rule. AFAIK it
shouldn't be there so I'll ignore it for the moment.
6) Still inside the 2nd parens we go left and find _fastcall.
This is a pointer to a _closure function taking an in parameter and
returning a pointer to a _fastcall.
7) Now outside the parens, to the right we find (int).
This is a pointer to a _closure function taking an in parameter and
returning a pointer to a _fastcall function taking an int parameter.
8) Now finally back to the left we find void.
This is a pointer to a _closure function taking an in parameter and
returning a pointer to a _fastcall function taking an int parameter
and returning void.
This is clearly not what we have either, as I erroneously specified
the parameter (line 33 of USB.cpp) as a pointer to a
SwitchMonitorCallback.
This seems like a compiler bug.
I hope you (Remy) or some other C++ guru will explain this to me.
TIA!
NOTE 1:
I don't know how to interpret the __fastcall unless my typedef is:
typedef void (__fastcall (__closure *SwitchMonitorCallback))(int);
which binds the __fastall to the function, but this doesn't work in
the example I posted in Attachments, causing the compiler to reject
the construction in line 41 of Main.cpp with:
[C++ Error] Main.cpp(41): E2285 Could not find a match for
'TUSB::TUSB(void (_fastcall * (_closure )(int))(int))'
|
|
| Back to top |
|
 |
Remy Lebeau (TeamB) Guest
|
Posted: Thu Dec 15, 2005 11:25 pm Post subject: Re: Please help me understand this error |
|
|
"Leroy Casterline" <casterle (AT) ccltd (DOT) com> wrote
| Quote: | Reading this using the right/left rule:
|
Your interpretation is not correct. See below.
| Quote: | Start at the identifier
|
There is no identifier listed in the signature.
| Quote: | Outside the 1st parens and now in the 2nd parens, to the
right we find (int).
This is a _closure function taking an int parameter.
|
That is not where the parameters are listed. The paranthesis on the
outer-right of the signature is where the parameters are.
| Quote: | Still inside the 2nd level of parens, to the right we find a *.
This is a _closure function taking an int parameter returning a
pointer.
|
That is not correct. The return value is never to the right of the
parameters. It is always on the far-left of the signature. In this case,
the return value is 'void'. There is no pointer return value being used.
| Quote: | Still inside the 2nd level of parens, to the right we find _fastcall.
|
To the right of what? I think you have your lefts and rights mixed up.
| Quote: | This is a _closure function taking an int parameter returning
a pointer to a _fastcall.
|
That is completely wrong. __fastcall is a calling convention, not a data
type. You can't have a pointer to a __fastcall, because __fastcall is not
an item in memory. A calling convention is a set of rules for the compiler
that govern how parameters are evaulated and the stack is managed. The
__fastcall in this case is the calling convention of the closure itself.
| Quote: | Outside the parens, to the right we find (int)
|
That is the true parameters.
| Quote: | This is a _closure function taking an int parameter returning a
pointer to a _fastcall function taking an int parameter.
|
Nope.
| Quote: | Finally to the left we find a void.
|
That is the return value.
| Quote: | This is a _closure function taking an int parameter returning a
pointer to a _fastcall function taking an int parameter and returning
void.
|
Nope. That is not correct.
| Quote: | So in the error that started this thread, the compiler was looking for
the TUSB constructor to have an argument that was a _closure
function taking an int parameter returning a pointer to a _fastcall
function taking an int parameter and returning void.
|
Nope, incorrect again.
| Quote: | But the TUSB constructor takes:
typedef void __fastcall (__closure *SwitchMonitorCallback)(int);
in which SwitchMonitorCallback is a pointer to a closure taking an int
parameter and returning a void. See NOTE 1 below.
|
That is the first correct thing you've said.
| Quote: | So clearly the expectations of the compiler differ from the
constructor argument type declared in the code.
|
That is not correct. What the compiler expects does match the original
typedef declaration. Like I told you earlier, how Borland displays the
signature of a closure in an error message IS NOT the true signature of the
closure. In order to interpret the error message, you need to first remove
the duplicate parameter list. Then you can interpret the remaining values
as a normal function pointer declaration with the __closure extension added
to it.
| Quote: | This seems like a compiler bug.
|
It is not. The bug is in your interpretation of the compiler's error
message output.
| Quote: | Now, continuing with the error message that was generated
by my misapplication of & to the function pointer:
void (_fastcall * (_closure *)(int) *)(int)
Again using the right/left rule and assuming the identifier would
be to the right of the * in the _closure part of the definition):
|
Your interpretation is still wrong, for the same reasons as above. The
'(int) *' to the immediate right of '(_closure *)' does not actually apply
to the actual signature that is seen by the compiler. The '&' that you
applied in your code produces the following signature:
void (_fastcall * (_closure *))(int)
The only difference between this and the original SwitchMonitorCallback
typedef is the extra '*' immediate following the __fastcall. Which is the
correct difference, since the '&' applied an extra level of pointer
indirection to the code you wrote.
| Quote: | I don't know how to interpret this using the right/left rule.
|
You don't, because that is not the correct rule to use to interpret these
signatures in the first place.
Gambit
|
|
| Back to top |
|
 |
Leroy Casterline Guest
|
Posted: Thu Dec 15, 2005 11:54 pm Post subject: Re: Please help me understand this error |
|
|
On Thu, 15 Dec 2005 15:25:51 -0800, "Remy Lebeau (TeamB)"
<no.spam (AT) no (DOT) spam.com> wrote:
| Quote: |
"Leroy Casterline" <casterle (AT) ccltd (DOT) com> wrote in message
news:5sl3q1hl9gucme3ctdt8bu2idv0bfadkip (AT) 4ax (DOT) com...
Reading this using the right/left rule:
Your interpretation is not correct. See below.
Start at the identifier
There is no identifier listed in the signature.
|
I know that, that's why I said I guessed I'd start to the right of the
identifier.
| Quote: | Outside the 1st parens and now in the 2nd parens, to the
right we find (int).
This is a _closure function taking an int parameter.
That is not where the parameters are listed. The paranthesis on the
outer-right of the signature is where the parameters are.
|
OK, but what does that (int) represent?
| Quote: |
Still inside the 2nd level of parens, to the right we find a *.
This is a _closure function taking an int parameter returning a
pointer.
That is not correct. The return value is never to the right of the
parameters. It is always on the far-left of the signature. In this case,
the return value is 'void'. There is no pointer return value being used.
|
Yes, as you noted below I got my rights and lefts reversed in a couple
of these. Sorry, I think that's a dyslexia thing. I thought I'd caught
all of these.
| Quote: | This is a _closure function taking an int parameter returning
a pointer to a _fastcall.
That is completely wrong. __fastcall is a calling convention, not a data
type. You can't have a pointer to a __fastcall, because __fastcall is not
an item in memory. A calling convention is a set of rules for the compiler
that govern how parameters are evaulated and the stack is managed. The
__fastcall in this case is the calling convention of the closure itself.
|
Yes, I understand this, but my definition is not complete until I've
added everything. At that point the __fastcall takes on its correct
meaning.
| Quote: | Outside the parens, to the right we find (int)
That is the true parameters.
|
How do you know this? Is it documented somewhere?
| Quote: | So in the error that started this thread, the compiler was looking for
the TUSB constructor to have an argument that was a _closure
function taking an int parameter returning a pointer to a _fastcall
function taking an int parameter and returning void.
Nope, incorrect again.
|
Why does the compiler not report the signature it's looking for?
Shouldn't it?
| Quote: | I don't know how to interpret this using the right/left rule.
You don't, because that is not the correct rule to use to interpret these
signatures in the first place.
|
So would the rule then be to remove parameters that are within parens,
then apply the right/left rule?
|
|
| Back to top |
|
 |
Remy Lebeau (TeamB) Guest
|
Posted: Fri Dec 16, 2005 1:18 am Post subject: Re: Please help me understand this error |
|
|
"Leroy Casterline" <casterle (AT) ccltd (DOT) com> wrote
| Quote: | OK, but what does that (int) represent?
|
I answered that earlier.
| Quote: | Outside the parens, to the right we find (int)
That is the true parameters.
How do you know this? Is it documented somewhere?
|
Because that is where the parameters are always specified, regardless of
whether __closure is used or not. A function signature is always in this
order:
return type
calling convention, and any vendor-specific extensions (__closure in
this case)
asteriks denoting pointers
identifier (if specified)
parameter list
| Quote: | Why does the compiler not report the signature it's looking for?
Shouldn't it?
|
It does. But as I've stated *several* times now, in the *specific* case of
a __closure type, the output reports MORE than is actually there. Why
Borland does that, who knows. __closure is a Borland-specific compiler
extension. They can do whatever they want with it. You just have to know
how to filter though the extra stuff to get that the real stuff.
| Quote: | So would the rule then be to remove parameters that are
within parens, then apply the right/left rule?
|
You don't apply the right/left rule at all. It is not a real rule,
especially since it is not very accurate and easily defeated. The grammer
of the language is dictated by the standard, not by these unofficial rules
that people make up for themselves.
Gambit
|
|
| Back to top |
|
 |
|
|
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
|
|