- Signals and slots? MOC? LOL. - 11 Updates
- json path in C++ - 1 Update
- A replacement for getters/setters ? - 4 Updates
- Swearing not considered harmful... - 2 Updates
- A replacement for getters/setters ? - 2 Updates
- store a reference to a std::function object - 4 Updates
- TDD considered harmful - 1 Update
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Feb 12 12:49AM How to subscribe to a button press event in my C++ GUI lib, "neogfx": button1.pressed([]() { /* do stuff */ }); // simplicity https://github.com/FlibbleMr/neogfx/ /Flibble |
Christian Gollwitzer <auriocus@gmx.de>: Feb 12 10:24AM +0100 Am 12.02.16 um 01:49 schrieb Mr Flibble: > How to subscribe to a button press event in my C++ GUI lib, "neogfx": > button1.pressed([]() { /* do stuff */ }); // simplicity nice, but still there are three sets of parenthesis that look gibberish. Compare with Tcl/Tk button .b1 -command { puts "You pressed me" } which creates a button and associates the command with it. This is one of the times where a preprocessor macro wouldn't be too bad. Unfortunately CPP is a really stupid one. In fact, a fully functional program in Tcl/Tk is three lines: package require Tk button .b -text "Press me" -command { tk_messageBox -message "You pressed me!" } pack .b I have yet to see another GUI library/language that can beat (or come close to) this conciseness. > https://github.com/FlibbleMr/neogfx/ Another general comment. It is impressive what you have achieved so far. I don't wnt to discourage you, but for a full fledged cross-platform widget set which I would consider in a GUI project, there is still a long way to go. One thing is platform integration. You seem to draw the widget elements completely on your own using OpenGL. This works now, but soon your widgets will look old-fashioned, because the design of computer interfaces follows fashion. Just run anything from before Win7 and you'll immediately understand. For this reason, the established widget sets use the native widgets under Windows and Mac OSX. Of course this requires many compromises, because not every option is supported everywhere and a big pile of work is required to achieve a common API for all supported systems. There is a somewhat intermediate solution by drawing your own widgets, but calling APIs which darw parts of teh native elements upon request. QT works this way, for instance, and ttk (the themable version of Tk). On Linux (or X11) it is even worse, there is no native widget set available. You'll have to constantly rewrite your library in order not to fall out of fashion, though the fashion is not so strong as on the other OSes. on OSX, in particular, if it doesn't look native (read: like any recent app from Apple) noone will buy it. That's just my 2 sausages. Christian |
leigh.v.johnston@googlemail.com: Feb 12 05:28AM -0800 Once I have implemented all the basic widgets I intend to move their drawing code into a default skin. Other skins will be available and there is no reason you couldn't add a skin that used native OS widget drawing helper functions so I don't believe my GUI lib will suffer from becoming outdated looking. /Flibble |
scott@slp53.sl.home (Scott Lurndal): Feb 12 01:48PM >How to subscribe to a button press event in my C++ GUI lib, "neogfx": > button1.pressed([]() { /* do stuff */ }); // simplicity I'd much rather register a callback function. Lambda's can impair readability, maintainability and modularity. Most cases where I program a button press event, it requires dozens of lines of code - not suitable for a lambda. An example (using GTK2): g_signal_connect(e_drawarea, "key-press-event", G_CALLBACK(keypress), this); gboolean c_env::keypress(GtkWidget *w, GdkEventKey *event, gpointer data) { c_env *ep = (c_env *)data; return ep->do_key(event); } /** * Handle a key press event within the drawing area for this environment. * * @param event The key press event descriptor * @returns TRUE to stop other handlers for this event, FALSE to propogate */ gboolean c_env::do_key(GdkEventKey *event) { s_screen_pos *spp = &e_kbc; s_page *pp = &e_pages[spp->sp_page]; if (pp->p_keyboard_mode == KM_TRANSMIT) { /* * Ignore the key, unless it is the RCV key. */ if (event->keyval == GDK_F11) { pp->p_keyboard_mode = KM_RECEIVE; e_xmit_handler->receive_mode(); update_statusline(); goto leave; } gdk_beep(); goto leave; } pp->p_keyboard_mode = KM_LOCAL; if ((event->keyval == GDK_Shift_L) || (event->keyval == GDK_Shift_R)) { goto leave; } ... 300 additional lines elided. leave: if (e_pixmap_dirty) expose(e_drawarea, &e_exposeall); return TRUE; } |
leigh.v.johnston@googlemail.com: Feb 12 05:57AM -0800 You are not forced to use a lambda you can use anything convertible to a std::function which includes ordinary callback functions however I disagree with your view re lambdas: embrace modern C++. |
Luca Risolia <luca.risolia@linux-projects.org>: Feb 12 03:39PM +0100 On 12/02/2016 14:48, Scott Lurndal wrote: > An example (using GTK2): > g_signal_connect(e_drawarea, "key-press-event", > G_CALLBACK(keypress), this); that's ugly to say the least. |
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Feb 12 02:45PM On 12/02/2016 13:48, Scott Lurndal wrote: > if (e_pixmap_dirty) expose(e_drawarea, &e_exposeall); > return TRUE; > } The problem here isn't my lambda but the fact that you have a 300 line function. Ever heard of functional decomposition? Functions can call other functions! Break it up mate (and embrace modern C++ and lambdas). /Flibble |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Feb 12 04:41PM +0100 On 2/12/2016 3:39 PM, Luca Risolia wrote: >> g_signal_connect(e_drawarea, "key-press-event", >> G_CALLBACK(keypress), this); > that's ugly to say the least. Yes, especially with the stringly typed event id. Cheers, - Alf |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Feb 12 04:43PM +0100 On 2/12/2016 3:45 PM, Mr Flibble wrote: > The problem here isn't my lambda but the fact that you have a 300 line > function. Ever heard of functional decomposition? Functions can call > other functions! Break it up mate (and embrace modern C++ and lambdas). Seconded. Cheers, - Alf |
scott@slp53.sl.home (Scott Lurndal): Feb 12 04:39PM >> g_signal_connect(e_drawarea, "key-press-event", >> G_CALLBACK(keypress), this); >that's ugly to say the least. Eye of the beholder. Less ugly than a 300 line lambda. |
scott@slp53.sl.home (Scott Lurndal): Feb 12 04:42PM >The problem here isn't my lambda but the fact that you have a 300 line >function. Ever heard of functional decomposition? Functions can call >other functions! Break it up mate (and embrace modern C++ and lambdas). It's a big switch on the keyval. Sure, could use a lookup table and call a function, but why? It works. It's easy to maintain. And it was written a long long time ago for X11R4 and ported later to GTK2. |
Christopher Pisz <nospam@notanaddress.com>: Feb 12 10:22AM -0600 Has anyone implemented an xpath equiv for json in C++? ermehgerd, it's killing me. I cannot believe there is not already some library that handles this. I found jsoncpp, but it crashes when you give it a path of more than 1 level. Can't find anything else -- I have chosen to troll filter/ignore all subthreads containing the words: "Rick C. Hodgins", "Flibble", and "Islam" So, I won't be able to see or respond to any such messages --- |
Daniel <danielaparker@gmail.com>: Feb 11 06:05PM -0800 On Thursday, February 11, 2016 at 5:42:06 PM UTC-5, Wouter van Ooijen wrote: > > /Flibble > Who? Fibble? The nonsense guy makes a remark that makes some sense? It's Flibble, if you please. Daniel |
Cholo Lennon <chololennon@hotmail.com>: Feb 12 09:36AM -0300 On 02/11/2016 05:48 PM, Scott Lurndal wrote: >> So instead of setter, we would always pass the object and the new value. > Well, I personally have no problem with getters and setters. I don't > see a need for a specific naming convention, however. I agree with you. Also IMO a getter/setter can have a non trivial implementation (i.e. provide a synchronous access to data). Another advantage over public data members is that calls to them can be deferred in time with std::function/std::bind. Regards -- Cholo Lennon Bs.As. ARG |
scott@slp53.sl.home (Scott Lurndal): Feb 12 01:39PM >provide a synchronous access to data). Another advantage over public >data members is that calls to them can be deferred in time with >std::function/std::bind. They also provide for the abstraction of the underlying data type, which then can be changed without changing the clients of the public class interface. |
Bo Persson <bop@gmb.dk>: Feb 12 05:12PM +0100 On 2016-02-11 18:15, K. Frank wrote: > Having said that, I don't think that getters/setters are > evil -- they're just something of a nuisance, especially > in simple settings. They become evil when people write code like pd.setAge(pd.getAge() + 1); and believe they have done something proper. Bo Persson |
Christian Gollwitzer <auriocus@gmx.de>: Feb 12 10:29AM +0100 Am 11.02.16 um 21:28 schrieb Mr Flibble: > ... you muthafucking cunt. Swearing is healthy. It relieves pain https://en.wikipedia.org/wiki/Hypoalgesic_effect_of_swearing but it works best if you are not used to it :P It also helps keeping some people from discussion threads. Christian |
JiiPee <no@notvalid.com>: Feb 12 03:16PM On 12/02/2016 09:29, Christian Gollwitzer wrote: > works best if you are not used to it :P > It also helps keeping some people from discussion threads. > Christian Starting fights/fighting on the streets also relieves pain (as adrealine is released), so according to your logic we should all start to fight? :) |
ram@zedat.fu-berlin.de (Stefan Ram): Feb 12 12:36AM > int age; >}; >So how to change that name without a setter? This depends on the definition of »setter«. |
ram@zedat.fu-berlin.de (Stefan Ram): Feb 12 01:23PM >Yes. The `Container` class should instead be like I tried to build a simplified model of the UB: #include <iostream> #include <ostream> #include <string> struct wrapper { const std::string & value; wrapper( const ::std::string & string ): value( string ) {} }; int main() { wrapper x( "" ); ::std::cout << x.value << '\n'; } The above program should have UB for reasons similar as in the OP. But the program below should not have UB anymore, due to the variable »s«. ... int main() { ::std::string s = ""; wrapper x( s ); ::std::cout << x.value << '\n'; } However, we get UB again when we change the type of »s«: ... int main() { char const * s = ""; wrapper x( s ); ::std::cout << x.value << '\n'; } While the result is the same, I prefer a style that avoids the char-*-strings from the language C, so (also no UB): ... using namespace ::std::literals; int main() { ::std::string s = ""s; wrapper x( s ); ::std::cout << x.value << '\n'; } But even without a conversion, we can reintroduce UB easily again (due to a literal also having a temporary value): ... using namespace ::std::literals; int main() { wrapper x( ""s ); ::std::cout << x.value << '\n'; } . |
Christof Warlich <christof.warlich1@gmail.com>: Feb 12 03:17AM -0800 Hi, I'm really desperate to understand why the following code does not work as expected: #include <functional> #include <iostream> struct Container { Container(const std::function<void()> &funtor): _functor(funtor) {} const std::function<void()> &_functor; }; struct Functor { Functor(int i): _i(i) {} void operator()() { std::cout << _i << std::endl; } int _i; }; int main() { Functor funtor(42); Container container(funtor); container._functor(); return 0; } It prints 0 instead of 42, and I really don't understand why. It works fine when I store the std::function object as a copy instead of just storing a reference in my container, i.e. when I remove the ampersend from line 5. But that's not an option because I finally want my operator() to return a result in one of the functors member variables. I'm obviously having some severe misconception w.r.t. the lifetime of the reference: Can anyone help me to understand what's really going on here? Thank you so much, Chris |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Feb 12 12:52PM +0100 On 2/12/2016 12:17 PM, Christof Warlich wrote: > return 0; > } > It prints 0 instead of 42, and I really don't understand why. It could just as well have crashed; it's Undefined Behavior. You're binding a reference to a temporary in the line I've marked "!!". The temporary's lifetime extends to the semicolon in that line. From then on you have a /dangling reference/. Note also that the convention with leading underscore for data member names is in direct conflict with the rules for reserved names. There are zillion naming conventions to choose from. No need to choose the worst. Cheers & hth., - Alf |
Christof Warlich <christof.warlich1@gmail.com>: Feb 12 04:22AM -0800 Am Freitag, 12. Februar 2016 12:53:11 UTC+1 schrieb Alf P. Steinbach: > > Container container(funtor); //!! ... > You're binding a reference to a temporary in the line I've marked "!!". > The temporary's lifetime extends to the semicolon in that line. From > then on you have a /dangling reference/. Again, just to fully understand: Is the temporary created because the compiler silently converts my Functor object to a (temporary) std::function<void()> object while passing to my container? > Note also that the convention with leading underscore for data member > names is in direct conflict with the rules for reserved names. There are > zillion naming conventions to choose from. No need to choose the worst. Ok, I'll happily take this advice as well :-). |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Feb 12 02:14PM +0100 On 2/12/2016 1:22 PM, Christof Warlich wrote: > Again, just to fully understand: Is the temporary created because the > compiler silently converts my Functor object to a (temporary) > std::function<void()> object while passing to my container? Yes. The `Container` class should instead be like struct Container { function<void()> functor_; Container( function<void()> functor ) : functor_( move( functor ) ) {} }; An alternative is to accept whatever type of functor the client code supplies, without invoking the (possibly costly for some types) type erasure of `std::function`, e.g. template< class Func > struct Container { Func functor_; Container( Func functor ) : functor_( move( functor ) ) {} }; template< class Func > auto make_container( Func f ) -> Container<Func> { return Container<Func>( move( f ) ); } In addition to possible improved efficiency for bloated but movable functors, this has the general advantage of not throwing away type information. Which in itself can also improve efficiency, because it allows the compiler to generate inline code for a call on class type functor. However, before being swayed by such arguments I'd measure, and most likely (and yes, I've made that decision a few times) I wouldn't care but just use std::function for simplicity and /clarity/. Cheers & hth., - Alf |
Jerry Stuckle <jstucklex@attglobal.net>: Feb 11 07:02PM -0500 On 2/11/2016 4:35 PM, Vir Campestris wrote: > to argue with you about it. > But for the avoidance of doubt you are wrong. > Andy No, I'm not. I'm telling you they don't perform unnecessary tests. They know a NAND gate in a design is a NAND gate. They don't need to test to see that it works. But they do test the circuit the NAND gate is in. If the circuit works, then they know the NAND gate is working. And no, I didn't speak to their engineers when the 7473 was in common use - I used that as an example. I spoke with them much more recently. And since my original background was EE, I spoke with them on an equal level - which is why companies call me back. I understand both the hardware and the software. So yes, I HAVE been working closely with "those who are". And I understand how they work. But you've just once again proven how dense you are. -- ================== Remove the "x" from my email address Jerry Stuckle jstucklex@attglobal.net ================== |
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment