|
k5054 wrote: That it should come from a prestigious university (it is that Harvard, right?), that should know better
That of course doesn't mean anything.
Large organizations, all large organizations, tend towards the average. That is inevitable due to size.
Besides that there is no determination about an individuals competence in general or for specific things.
You can also google for variations of the code library and find variations. I found a variation that looked like it was C++. No memory leak in that (very brief look) because it was returning 'string'. So possible that someone familiar with C++ but not so much C converted it. And also possible it wasn't even the person teaching the class, just that the teacher found it and is using it.
|
|
|
|
|
Harvard esp. so
Charlie Gilley
“They who can give up essential liberty to obtain a little temporary safety deserve neither liberty nor safety.” BF, 1759
Has never been more appropriate.
|
|
|
|
|
First - my apology for taking so much space, I promise to delete ALL after I get this solved - unless it is of benefit to forum...
Here is the current status of "main menu with sub menus "
using "connect" with lambda - it works only on FIRST menu.
I believe the sender and subsequent trigger are WRONG.
I am enclosing the code which creates
the " main menus with their associated sub menus ".
The code works as expected / desired.
The issue is using "connect" as a trigger..sub menu selection...
{ for (index = 0; index < list.size(); ++index)
{
{ { subMenu[index] = m_ui->menuWindow_cpntrol;
subMenu[index] = subMenu[index]
->addMenu(list[index] + " # " + QString::number(index));
mainAction[index] = subMenu[index]->menuAction();
subSize = list_array[index].size();
for (index_sub = 0; index_sub < subSize; ++index_sub)
{ { { subAction[index_sub]= subMenu[index]->addAction(list_array[index][ index_sub] + " #" + QString::number( index_sub));
subAction[index_sub]->setCheckable(true);
} } } }
QAction* tempAction = new QAction(); tempAction->setCheckable(true);
{ }
{ {
} }
{
{}
} } }
{
}
}
Here is my current, working with FIRST menu code.
I do apology for "debug" junk code , it is a little hard to follow the real code.
{
#ifdef LAMBDA
text = "START TASK DEBUG lambda ... ";
text += Q_FUNC_INFO;
text += QString::number(__LINE__);
qDebug() << text;
#endif
int submenu_index = -1;
int mainmenu_index= -1;
QString mainMenu;
QObject obj;
qDebug() << " index_sub " << index_sub ; obj.connect(subMenu[index_sub],&QMenu::triggered,subMenu[index_sub ],[](QAction* action)
{
QString path=action->text();
#ifdef LAMBDA
qDebug() << "TEST need index ?? " << path;
qDebug()<<"path (sub menu trigger ) "<< path ;
#endif
QWidget* parent=action->parentWidget();
path = QString("(%1)").arg(parent->actions().indexOf(action));
#ifdef LAMBDA
qDebug()<<"path (sub menu ) with index TOK "<< path ;
#endif
while(parent)
{
QMenu* menu=qobject_cast<QMenu*>(parent);
QString title=menu->title();
#ifdef LAMBDA
qDebug()<<"title (main menu ) "<< title ;
#endif
path+="->"+title;
qDebug()<<"path (title) "<< path ;
parent=parent->parentWidget();
#ifdef LAMBDA
qDebug()<<"TRACE while first entry crasher ... "<< __LINE__ ;
#endif
if(parent)
{
#ifdef LAMBDA
qDebug()<<"TRACE parent widget (??) valid continue ... "<< __LINE__ ;
#endif
QMenu* menu=qobject_cast<QMenu*>(parent);
#ifdef LAMBDA
qDebug()<<"TRACE parent widget main menu (??)continue "<< __LINE__ ;
#endif
int index=0;
const QList<QAction*> actions=menu->actions();
#ifdef LAMBDA
qDebug()<<"TRACE parent widget main menu list (actions) continue "<< __LINE__ ;
#endif
for(const QAction *act : actions)
{
#ifdef LAMBDA
qDebug()<<"TRACE for(const QAction *act : actions) "<< __LINE__ ;
#endif
#ifdef LAMBDA
qDebug()<<"TRACE title (??) " << title << __LINE__ ;
#endif
#ifdef LAMBDA
qDebug()<<"TRACE act->text()==title "<< act->text() << __LINE__ ;
#endif
if(act->text()==title)
{
#ifdef LAMBDA
qDebug()<<"TRACE main menu found act->text()==title "<< act->text() << __LINE__ ;
#endif
path = QString("(%1)").arg(index);
#ifdef LAMBDA
#endif
#ifdef LAMBDA
qDebug()<<"HERE path (main menu -> sub menu) "<< path ;
#endif
goto TEMP_LABEL;
}
#ifdef LAMBDA
qDebug()<<"TRACE "<< __LINE__ ;
#endif
index++;
}
}
} TEMP_LABEL: qDebug()<<" FINAL (??) "<< path;
} );
QString::number(__LINE__);
#ifdef LAMBDA
text = "END TASK DEBUG lambda... ";
text += Q_FUNC_INFO;
text += QString::number(__LINE__);
qDebug() << text;
#endif
return 0;
}
'
Here is more junk - actual debug output when first "main menu" and its "first sub menu " is selected - by triggering on first sub menu.
19:53:10: Starting /mnt/A_BT_DEC10/BT__PROGRAMS/A_JAN11/A_BT_LIBRARY/mdi/mdi...
Warning: Ignoring XDG_SESSION_TYPE=wayland on Gnome. Use QT_QPA_PLATFORM=wayland to run on Wayland anyway.
"START TASK DEBUG lambda ... int MainWindow_Bluetooth::setupLambda()89"
index_sub 0
"END TASK DEBUG lambda... int MainWindow_Bluetooth::setupLambda()213"
TEST need index ?? "SubWindow LOCAL terminal all options #0"
path (sub menu trigger ) "SubWindow LOCAL terminal all options #0"
path (sub menu ) with index TOK "(0)"
title (main menu ) "terminal # 0"
path (title) "(0)->terminal # 0"
TRACE while first entry crasher ... 138
TRACE parent widget (??) valid continue ... 143
TRACE parent widget main menu (??)continue 149
TRACE parent widget main menu list (actions) continue 154
TRACE for(const QAction *act : actions) 163
TRACE title (??) "terminal # 0" 166
TRACE act->text()==title "Tile subwindows " 169
TRACE 194
TRACE for(const QAction *act : actions) 163
TRACE title (??) "terminal # 0" 166
TRACE act->text()==title "Cascade subwindows " 169
TRACE 194
TRACE for(const QAction *act : actions) 163
TRACE title (??) "terminal # 0" 166
TRACE act->text()==title "Maximize current subwindow " 169
TRACE 194
TRACE for(const QAction *act : actions) 163
TRACE title (??) "terminal # 0" 166
TRACE act->text()==title "" 169
TRACE 194
TRACE for(const QAction *act : actions) 163
TRACE title (??) "terminal # 0" 166
TRACE act->text()==title "" 169
TRACE 194
TRACE for(const QAction *act : actions) 163
TRACE title (??) "terminal # 0" 166
TRACE act->text()==title "terminal # 0" 169
TRACE main menu found act->text()==title "terminal # 0" 175
HERE path (main menu -> sub menu) "(5)"
FINAL (??) "(5)"
19:53:27: /mnt/A_BT_DEC10/BT__PROGRAMS/A_JAN11/A_BT_LIBRARY/mdi/mdi exited with code 0
Here is the failure when ANY main menu , with exception of first one , is used.
That points to probable cause - wrong sender....
19:31:40: Starting /mnt/A_BT_DEC10/BT__PROGRAMS/A_JAN11/A_BT_LIBRARY/mdi/mdi...
Warning: Ignoring XDG_SESSION_TYPE=wayland on Gnome. Use QT_QPA_PLATFORM=wayland to run on Wayland anyway.
"START TASK DEBUG lambda ... int MainWindow_Bluetooth::setupLambda()89"
index_sub 0
"END TASK DEBUG lambda... int MainWindow_Bluetooth::setupLambda()213"
19:31:54: /mnt/A_BT_DEC10/BT__PROGRAMS/A_JAN11/A_BT_LIBRARY/mdi/mdi exited with code 0
|
|
|
|
|
Best guess? Wrong forum. AFAICT this is a QT issue. QT ≠ C++. While QT does use C++ as a base, it's a framework on top of C++. You are more likely to get an answer either from a QT specific forum, or from the site you got your examples from.
"A little song, a little dance, a little seltzer down your pants"
Chuckles the clown
|
|
|
|
|
So you do not think this is my fault - wrong usage of C++?
"connect " is Qt specific , but lambda is C++ or am I wrong?
I did post same on QT forum and I fully expect somebody to say _ this is C++ code problem "...
But if I continue this discussion here ... I will end up banned......
.,..in that case..
Thanks and have a swell day...
|
|
|
|
|
I'm basing this on the runtime error, which you believe is something to do with "wrong sender". That seems to me to be a QT issue, not a C++ issue. AFAIK, there's no such thing as a "sender" in the C++ standard. Which points to QT, not C++
"A little song, a little dance, a little seltzer down your pants"
Chuckles the clown
|
|
|
|
|
OK, it is Qt issue..
I'll give few days for somebody else to respond , then I
will take it down.
Is that OK?
|
|
|
|
|
I'd just leave it, unless more senior members disagree. Otherwise, there's a discussion that someone else might stumble on and wonder what was going on. Who knows, maybe someone will stumble on this at some time in the future and be able to explain what the issue is.
"A little song, a little dance, a little seltzer down your pants"
Chuckles the clown
|
|
|
|
|
Here is my analysis in a nutshell.
The "issue" is with Qt "connect" function / process...
I have the "connect" working as expected , but ...
I am passing parameters / indexes - main menu and submenu...
...that is what I thought I was doing , but ...
the "parameters " values are NOT dynamic AKA
used when "connect" is activated - click on sub menu.
In my test - the main menu should be 0
and the submenu anything from 0 to 7
The code I have found uses lambda
and it analyze the "connect" AND
RETRIEVES the dynamic values of both indexes.
I need the indexes to do what the menu / submenu
is about - process something...
I have modified the code because i
CANNOT debug / step thru the lambda code !
So - the lambda code does work BUT ...
it only works/ retrieves main menu index of 0
That is the real error and I am seeking assistance
to find out why
it only works on FIRST menu.
My uneducated guess is -
the obvious place
to look is where
the code step thru "main menu list"...
if(parent)
{
QMenu* menu=qobject_cast<QMenu*>(parent);
int index=0;
const QList<QAction*> actions=menu->actions();
for(const QAction *act : actions)
{
if(act
->text()==title)
{
path+=QString("(%1)").arg(index);
break;
}
index++;
}
}
|
|
|
|
|
Salvatore Terress wrote: I have modified the code because i
CANNOT debug / step thru the lambda code !
That does seem to be an issue with lambdas - at least gdb doesn't seem to be able to step into lambdas. I haven't tried it myself, so I can only go by what I've seen elsewhere on the subject.
But.
Why don't you just extract the function definition from the lambda and define it as a normal function. I think that should work
foo( a, b, c, [](int x, int y) { return val; } );
becomes
int lambda_f( int x, int y)
{
return val;
}
foo(a, b, c lambda_f);
"A little song, a little dance, a little seltzer down your pants"
Chuckles the clown
|
|
|
|
|
Yes, I am now using plain function to analyze results of "connect".
My code is still pretty messy , hard to read , since I added debug...
But I can step thru it , so the debug is "leftover from lambda"...
I got my code doing what I need...
In retrospect - the problem was what I suspected from the start
understanding "connect" and PLACING it into correct place.
PS
As far as getting help from forums - it was ABOUT 80% of "RTFM" and other
"fill the blanks" to make "small talk"...
|
|
|
|
|
Salvatore Terress wrote: then I
will take it down.
Is that OK? No, because that leaves orphaned messages which make little sense to others reading it.
Incidentally, I did look at this code earlier and tried to make it readable, by removing all those extra braces in the first sample, but it still made little sense. As to the second sample, why are you trying to use a lambda expression for all that code? Use a proper function/member subroutine so you can see better what is (supposed to be) happening. And, as k5054 says, this is most likely a Qt issue rather than simple C++.
|
|
|
|
|
Richard MacCutchan wrote: why are you trying to use a lambda expression for all that code?
I agree with that strongly.
If the developer can't figure out the lambda code then they shouldn't be using it in the first place. That isn't being denigrating since to me they are almost always confusing so I never voluntarily use them. They do nothing but make the code obtuse and the more complicated it is the more that becomes true.
It also has the following impacts.
- Maintenance programmers must figure it out.
- I have seen more than one senior developer use it incorrectly making the code less efficient.
Seems almost like there could be a coding guideline in that. If methods must be, for example, less than 100 lines of code, then seems that lambda expressions should also be limited perhaps to something like 10 clauses (or less.)
|
|
|
|
|
Please read my previous reply.
It was not my choice to use lambda - I took the code from another forum contributor...
Using lambda was not that difficult - the code flow was pretty logical.
The issue was - for whatever reason I could not "step thru" the lambda code...
|
|
|
|
|
I fully understand that. What I'm saying is that there is no reason that you to have to use a lambda. You can extract the function body and use a normal function pointer instead. And a normal function can be debugged by putting a break point a the function entry point.
I'm not sure what your stumbling point is here. Consider:
struct S {
int i;
double d;
};
bool cmp_double(const S& s1, const S&s2) {
return s1.d < s2.d;
}
int main()
{
std::vector<S> vs;
std::sort( vs.begin(), vs.end(), cmp_double);
std::sort( vs.begin(), vs.end(), [](const S& x, const S&y) { return x.d < y.d } );
}
The point is, the two sorts do exactly the same thing. So there's no reason you can't extract the lambda and use the named function as a parameter. If you're having trouble understanding this, you need to go back to your study material and review lambdas. I can recommend Justin Turners C++ weekly you-tube blog [https://www.youtube.com/playlist?list=PLs3KjaCtOwSZ2tbuV1hx8Xz-rFZTan2J1](https://www.youtube.com/playlist?list=PLs3KjaCtOwSZ2tbuV1hx8Xz-rFZTan2J1) Just follow the link and then search for lambda, and watch the videos. It might be worth doing even if you do understand lambdas. It's not like another perspective can't help with the understanding.
"A little song, a little dance, a little seltzer down your pants"
Chuckles the clown
|
|
|
|
|
Salvatore Terress wrote: It was not my choice to use lambda - I took the code from another forum contributor
Pretty sure that is a choice. As suggested in the other post you can rewrite it.
Not sure I have ever used a code sample where I did not modify it.
|
|
|
|
|
|
It counts the initial characters in the string until the pointer is aligned on a longword boundary. It then uses some clever bit manipulations to count the rest of the characters four at a time. If you run that code in the debugger you will be able to see exactly what happens.
|
|
|
|
|
Presumably already clear what the 4/8 block is used in the first place.
Googling with following provides some answers.
explain strlen himagic lomagic
Following line is the key
if (((longword - lomagic) & ~longword & himagic) != 0)
I tried eye balling that and using examples in my head but still not clear. I believe it is relying on arithmetic overflow.
If I wanted to understand that I would write up some test code with examples characters (4 blocks) with zero at the end (position 4, 3, 2, 1). Then have it print the results of each clause in the above if using binary representation (1 and 0) to see how the bits look for each different example and for each part of the clause.
Perhaps as a learning experience also copy that code into your own space and then write a test jig to time results via that and using the more straightforward (just by char) code. You should start with a large number of runs like probably at least 100,000.
|
|
|
|
|
More update
Found the crasher - wrong "exit" from "for" loop looking for main menu.
Having issues (expected ) using other than first main menu...
UPDATE
I am posting this to show SOME progress.
I did pepper the original with handful of "debug"...
( I need to add comments about what the code does...)
So far it works with main menu = 0 and all its sub menus - SUCCESS.
I got the sub menu index - so part of my goal is done.
Now I need to find the "main menu" index and then find the "crasher"..
BTW the author deserves LARGE credit for the code..
int MainWindow_Bluetooth::setupLambda ( void )
{
#ifdef LAMBDA
text = "START TASK DEBUG lambda ... ";
text += Q_FUNC_INFO;
text += QString::number(__LINE__);
qDebug() << text;
#endif
QObject obj;
qDebug() << " index_sub " << index_sub ; obj.connect(subMenu[index_sub],&QMenu::triggered,subMenu[index_sub ],[](QAction* action)
{
QString path=action->text();
#ifdef LAMBDA
qDebug() << "TEST need index ?? " << path;
qDebug()<<"path (sub menu trigger ) "<< path ;
#endif
QWidget* parent=action->parentWidget();
path = QString("(%1)").arg(parent->actions().indexOf(action));
#ifdef LAMBDA
qDebug()<<"path (sub menu ) with index TOK "<< path ;
#endif
while(parent)
{
QMenu* menu=qobject_cast<QMenu*>(parent);
QString title=menu->title();
#ifdef LAMBDA
qDebug()<<"title (main menu ) "<< title ;
#endif
path+="->"+title;
qDebug()<<"path (title) "<< path ;
parent=parent->parentWidget();
#ifdef LAMBDA
qDebug()<<"TRACE "<< __LINE__ ;
#endif
if(parent)
{
QMenu* menu=qobject_cast<QMenu*>(parent);
#ifdef LAMBDA
qDebug()<<"TRACE "<< __LINE__ ;
#endif
int index=0;
const QList<QAction*> actions=menu->actions();
for(const QAction *act : actions)
{
#ifdef LAMBDA
qDebug()<<"TRACE "<< __LINE__ ;
#endif
if(act->text()==title)
{
path+=QString("(%1)").arg(index);
#ifdef LAMBDA
qDebug()<<"path (main menu -> sub menu) "<< path ;
#endif
break;
}
#ifdef LAMBDA
qDebug()<<"TRACE "<< __LINE__ ;
#endif
index++;
}
}
}
qDebug()<<" FINAL (??) "<< path;
} );
#ifdef LAMBDA
text = "END TASK DEBUG lambda... ";
text += Q_FUNC_INFO;
text += QString::number(__LINE__);
qDebug() << text;
#endif
return 0;
}
OUTPUT
11:57:03: Starting /mnt/A_BT_DEC10/BT__PROGRAMS/A_JAN11/A_BT_LIBRARY/mdi/mdi...
Warning: Ignoring XDG_SESSION_TYPE=wayland on Gnome. Use QT_QPA_PLATFORM=wayland to run on Wayland anyway.
QObject::connect(QAction, Unknown): invalid nullptr parameter
"START TASK DEBUG lambda ... int MainWindow_Bluetooth::setupLambda()89"
index_sub 0
"END TASK DEBUG lambda... int MainWindow_Bluetooth::setupLambda()167"
TEST need index ?? "SubWindow LOCAL terminal all options #0"
path (sub menu trigger ) "SubWindow LOCAL terminal all options #0"
path (sub menu ) with index TOK "(0)"
title (main menu ) "terminal # 0"
path (title) "(0)->terminal # 0"
TRACE 128
TRACE 134
TRACE 141
TRACE 153
TRACE 141
TRACE 153
TRACE 141
TRACE 153
TRACE 141
TRACE 153
TRACE 141
TRACE 153
TRACE 141
path (main menu -> sub menu) "(0)->terminal # 0(5)"
title (main menu ) "Window control"
path (title) "(0)->terminal # 0(5)->Window control"
TRACE 128
TRACE 134
11:57:22: /mnt/A_BT_DEC10/BT__PROGRAMS/A_JAN11/A_BT_LIBRARY/mdi/mdi crashed.
I do not get what is missing - the error "points" at "action".
Code snippet :
QObject::connect(&MainWindow_Bluetooth::subMenu,&QMenu::triggered,&MainWindow_Bluetooth::subMenu,[](QAction* action)
{ QString path=action->text();
QWidget* parent=action->parentWidget();
path+=QString("(%1)").arg(parent->actions().indexOf(action));
while(parent)
{
QMenu* menu=qobject_cast<QMenu*>(parent);
QString title=menu->title();
path+="->"+title;
parent=parent->parentWidget();
if(parent)
ERROR :
/mnt/A_BT_DEC10/BT__PROGRAMS/A_JAN11/A_BT_LIBRARY/terminal_Bluetooth/mainwindow_Bluetooth_copy.cpp:42: error: C++ requires a type specifier for all declarations
mainwindow_Bluetooth_copy.cpp:42:10: error: C++ requires a type specifier for all declarations
QObject::connect(&MainWindow_Bluetooth::subMenu,&QMenu::triggered,&MainWindow_Bluetooth::subMenu,[](QAction* action)
^
modified 3-Feb-24 16:02pm.
|
|
|
|
|
No, the error is on QObject::connect(... . You cannot call a member function of a class(*). You have to insantiate an object of the class and call the member function on that object. Something like:
QObject obj();
obj.connect();
[*] Unless the member function is a static member function. I doubt that is the case here.
Mircea
|
|
|
|
|
Certainly looks to me that at a minimum you are missing a paren in the first line/statement.
|
|
|
|
|
That's what I thought too, but then I saw the comment //lambda just after the opening brace. I think that the following code is all a lambda expression as a parameter to the QObject::connect() call. I think the OP could have cleaned up the submission with something like
QObject::connect(&MainWindow_Bluetooth::subMenu,&QMenu::triggered,&MainWindow_Bluetooth::subMenu,[](QAction* action){ });
"A little song, a little dance, a little seltzer down your pants"
Chuckles the clown
|
|
|
|
|
I suggest looking through all your code (there really is no "points" when something comes to an "action" especially when ALL of the code is not available) for "typedef". Then, assuming these errors are sallying forth from the mingw/gnu/etc compiler you're using, and have no code associated with them to differentiate one from the other, change any typedefs of the form:
(this only an example, not the code you have)
std::vector<int>::size_type
To
std::vector<int>::size_type size
See if any errors go away.
modified 2-Feb-24 14:34pm.
|
|
|
|
|
Thanks, the code is an example I found, so I am just starting to modify it for my use.
I stopped when I received the error.
I actually got more , but I just do not see how to fix the "action".
The "problem" is - the original error "pointed " on "connect" and this error "points " on "action"
Let me work on this...maybe I can actually clean up the whole "lambda".
|
|
|
|