Re: Support service
On Mon, 14 Feb 2022 at 20:17, Martin Owens wrote: > On Mon, 2022-02-14 at 20:08 +0000, Jonathan Wakely via gtkmm-list > wrote: > > People work on them for free, > > No, people work on them for lots of money; they distribute them for > free. > Well I think it's a bit of both, in practice. I doubt every contributor to gtkmm is paid to do so. ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: Support service
On Mon, 14 Feb 2022, 19:50 David Gasa i Castell via gtkmm-list, < gtkmm-list@gnome.org> wrote: > Dear project team, > > I write you to say that it doesn't work. > This is a useless statement. Nobody can help something so vague, what does "doesn't work" mean? > I've been using Gtkmm libraries since 2.x (even if some refactorings and > changes were made thereafter) but I still need your help. > > Having a reference helps but it's not enough. > > When I submitted questions directly to the project programmers, they > pointed me to submit in a list... > That's how open source projects usually work. People work on them for free, but they don't want strangers contacting them directly expecting support. The mailing list is the right way to seek help. but a list that nobody has the responsibility to answer in an appropriate > manner... does not help, either. Silence does not help. > > I'd like to know, if possible, why some of my questions (and other users' > as well), if so, are not properly answered and how to solve it. > Make sure you are asking good questions. http://www.catb.org/~esr/faqs/smart-questions.html > I should ask you to improve the support. > > Is it possible to create a payment subscription quotes or on demand > service in order to receive assistance ? > It took me less than ten seconds to find this page: https://gtkmm.org/en/commercial_support.html ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: Additional Glib::RefPtr Safety Mechanism
On Sat, 31 Aug 2019, 11:55 Karsten Pedersen, wrote: > I have yet to see it in any gtkmm code (you will be pleased to hear) > but my personal opinion is that it is surely a nice idea to attempt > to make C++ 100% safe rather than having to rely purely on the skills of > a developer. This is generally the trend in Rust communities but it > seems the culture in C++ communities is that not all safety is > necessary. > With Rust that safety is checked and enforced by the language and the compiler. The language rules mean that most checking can have no overhead at runtime. Your solution incurs non-zero runtime cost (extra reference counting) which can't be optimised away in general. Being 100% safe would be nice, but there's a trade off. Achieving it in C++ is either impossible or very expensive. I don't agree that "it is surely a nice idea to attempt to make C++ 100% safe". It's unrealistic to pretend otherwise. ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: Additional Glib::RefPtr Safety Mechanism
On Thu, 29 Aug 2019 at 21:27, Karsten Pedersen wrote: > Hi all, > > One area of C++ that always frustrates me is safety. Smart pointers > such as the Glib::RefPtr go a good way to avoid dangling pointers, use > after free, etc. However one area where this (and std::shared_ptr) is > lacking is that it is very easy for "this" to dangle and there really > is no protection against it. Check out a very simple example here: > > https://github.com/osen/sr1/blob/master/src/tests/dangling_this.cpp > > Is this actually a common problem that needs to be solved? It seems like a solution in search of a problem. IMO you should just avoid using globals like this when possible, and use them carefully when necessary. For the shared_ptr example, you can solve the problem simply by copying the global into a local variable in the one function that needs to do it. That way you don't pay the cost in every function that uses operator-> void broken() { auto keepalive = d; d = std::sr1::shared_ptr(); dummy = 9; } That keeps *this alive until the end of the function. Or slightly more efficiently: void broken() { auto keepalive = std::move(d); d = std::sr1::shared_ptr(); dummy = 9; } ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: C++17
On 14 April 2018 at 15:38, Murray Cumming wrote: > On Thu, 2018-04-12 at 21:10 +0100, Jonathan Wakely wrote: >> On 12 April 2018 at 21:02, Murray Cumming wrote: >> > I've just released a version of libsigc++-3.0 (currently unstable) >> > that >> > requires C++17. This means that gtkmm-4.0 (currently unstable) >> > requires >> > C++17 too. I should have mentioned it first, but I think this is >> > fine. >> >> What are you using from C++17? > > Nothing major. Just some constexpr if, std::apply() and std::invoke(): > https://github.com/libsigcplusplus/libsigcplusplus/commits/master That's fine then - no ABI worries with those bits. >> GCC's C++17 implementation is not stable yet, so there are still ABI >> changes possible between GCC 8 and GCC 9. >> >> IIRC we've already introduced some (minor) incompatibilities between >> the std::variant in GCC 7 and GCC 8. > > gtkmm-4.0 is itself unstable, so that's not a problem. And I see no > sign that GTK+ 4.0 will become stable any time soon. OK, cool. I wanted to be sure you wouldn't end up with a dependency on something unstable, but it sounds like that won't be a problem. ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: C++17
On 12 April 2018 at 21:02, Murray Cumming wrote: > I've just released a version of libsigc++-3.0 (currently unstable) that > requires C++17. This means that gtkmm-4.0 (currently unstable) requires > C++17 too. I should have mentioned it first, but I think this is fine. What are you using from C++17? GCC's C++17 implementation is not stable yet, so there are still ABI changes possible between GCC 8 and GCC 9. IIRC we've already introduced some (minor) incompatibilities between the std::variant in GCC 7 and GCC 8. ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: get/set wrap methods.
On 23 February 2018 at 14:55, Pavlo Solntsev wrote: > Daniel, > > now it is clear. I didn't and still don't understand exactly how internal > data members are represented in the generated class (I have no access to my > code now) but the situation I have by returning a reference is clear. BTW > does it make sense to think about shared_ptr as returned value for getter? > No, because unless you keep a copy of the shared_ptr as a member, you will get a new shared_ptr each time you call it, which doesn't share ownership with the previous ones. So now you have the shared_ptr overhead (reference counting) and inconvenience (needing to use operator* to access the value), without any sharing. You might as well just return by value, or have a Glib::ustring member. ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: get/set wrap methods.
On 23 February 2018 at 14:37, Jonathan Wakely wrote: > On 23 February 2018 at 14:22, Pavlo Solntsev wrote: > >> Yes, I did. because my goal is to get >> const T& get_name()const >> method. I need to return a reference. >> >> > Then you need to change your type to have a using member. > Sorry, for the typo, that was meant to say "ustring member" > > You can't have it both ways (return a reference, but not have something to > bind the reference to). > > Pick one. > ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: get/set wrap methods.
On 23 February 2018 at 14:22, Pavlo Solntsev wrote: > Yes, I did. because my goal is to get > const T& get_name()const > method. I need to return a reference. > > Then you need to change your type to have a using member. You can't have it both ways (return a reference, but not have something to bind the reference to). Pick one. ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: LInking problems after switch to gcc-6.4.0
On 8 January 2018 at 10:19, Daniel Boles wrote: > I guess it's probably this: > https://stackoverflow.com/a/33395489/2757035 Yup, GCC 5+ has two versions of std::string, to link functions using std::string both the caller and callee need to agree on which version of std::string is used. Everything needs to be compiled consistently, to use the same version of std::string. ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: Why do Glib::ustring::operator[] and at() return values, not references?
On 28 June 2017 at 09:39, Daniel Boles wrote: > But the main drawback I could think of is this: It would change semantics > for anyone currently using auto some_character = non_const_ustring[N], as > the auto would now capture the proxy type, not a gunichar. To get the > latter, the type would have to be explicitly specified to invoke the > conversion operator. Or is there a clever way around this that I don't know? There's no way around it. There have been proposals for an "operator auto" that would make it possible to control the deduced type, mostly for use by expression templates, but nothing that is part of C++ yet. Another downside of a proxy is it can outlive the string, so this would be undefined (without some internal complexity to track lifetimes): auto c = Glib::ustring("foo")[0]; c = 'b'; // tries to modify the expired temporary Again, this only happens when using 'auto' because otherwise there's no attempt to write back into the ustring: gunichar c = Glib::ustring("foo")[0]; c = 'w'; // just modifies c ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: C++17's string_view (was Re: Making use of move semantics?)
On 13 June 2017 at 08:31, Murray Cumming wrote: > > So, I think: > 1. We would use std::string_view everywhere if all the C functions took > a length instead of assuming null-termination. That's not going to > happen. > > 2. Overriding all methods to take either a const char* or a std::string > (ignoring ustring for now), would avoid the extra array copy, but I > don't think it's worth it other than for methods that typically take > very large strings. > > 3. GTK+ functions that take very large strings tend to take a length, > to avoid the need for copying. For instance, > gtk_text_buffer_set_text(). We could take std::string_view there, but > then our use of std::string_view::to_string() would be wasteful when > someone passes a std::string to our method. > > This is discouraging, so I hope I'm wrong about something. > > Nope, you're correct. string_view is great if you stay in C++ world, but suboptimal when you need to pass the string to libc functions or C APIs taking null-terminated strings. One possible approach (which I have no experience of in practice, only in theory) is to use string_view objects which explicitly include the null-terminator in their length: template inline std::basic_string_viewmake_null_terminated_view(const C* s) noexcept { return { s, T::length() + 1 }; } template inline bool is_null_terminated_view(std::basic_string_view sv) noexcept { return sv.length() && !sv.back(); } And/or create your own cstring_view / zstring_view type which is guaranteed to be null-terminated: struct cstring_view : std::string_view { cstring_view(const char* s) : std::string_view(s, traits_type::length(s)+1) { } }; Unlike std::string which has a null-terminator after its content that isn't counted in the length, these string views would count the null character as part of their content. You'd need a little more care to use this (i.e. when using the length remember to subtract one where appropriate) but it does mean you can pass around views to null-terminated strings efficiently (along with their length, which is the advantage over a raw pointer). ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: enums that are really just sets of constants
On 23 May 2017 at 15:29, Daniel Boleswrote: > > On 23 May 2017 at 15:12, Kjell Ahlstedt wrote: > >> >> I don't understand how you can have, for instance >> void f(ResponseType r); >> if ResponseType is an uninstantiable class. If ResponseType is the name >> of a class, and you want to treat it as if it were the name an enum, >> wouldn't it require something like >> > > D'oh. Right! Carry on. :) > > The language seems to make this overcomplicated. I need to search for info > on whether anyone ever proposed a scoped but implicitly convertible enum, > and if so, why it never got anywhere. > Then we'd have three types of enum ... that doesn't seem like it'd be an improvement. ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: enums that are really just sets of constants
On 23 May 2017 at 08:51, Kjell Ahlstedtwrote: > Den 2017-05-13 kl. 10:04, skrev Kjell Ahlstedt: > > Yet another suggestion in https://bugzilla.gnome.org/ > show_bug.cgi?id=86864#c43 > > Can we decide what to do with the few enums that we want to be implicitly > convertible to int? My suggestion in https://bugzilla.gnome.org/ > show_bug.cgi?id=86864#c43 is > > class ResponseType_Enum final > { > public: > enum ResponseType > { > NONE = -1, > REJECT = -2, > ACCEPT = -3, > ... > }; > ResponseType_Enum() = delete; > }; > using ResponseType = ResponseType_Enum::ResponseType; > > I tried to make a mixture of a plain (old-style) enum and an enum class. > It shall be implicitly convertible to int, and its enumerators shall be > scoped. In other respects it shall be possible to use it as if it's an > enum, e.g. > > ResponseType r = ResponseType::REJECT; > int i = r; > but not > r = REJECT; > i = REJECT; > and preferably not > r = i; > > Daniel has remarked that _Enum is not a good suffix for a class name. I > agree. Can you think of a better suffix? I don't want to call the class > *ResponseType*. That would clash with *using ResponseType = ...*. If it > shall be possible to use *ResponseType* as if it's the name of an enum, > it must be the name of an enum or an alias for a name of an enum. Or are > there other possibilities that are not too complicated? > Would Response::Type work? struct Response final { enum Type { ... }; Response() = delete; }; void foo(Response::Type = Response::REJECT); ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: Making use of move semantics?
On 21 May 2017 at 10:36, Daniel Boles wrote: > I still occasionally find myself reflexively std::move()ing strings into > glibmm/gtkmm functions that I unconsciously see as taking ownership of > their arguments - only to realise it makes no difference because all of > them take strings as const&. > > This made me wonder whether there are any cases where, if the user > instructs so by using std::move(), glibmm/gtkmm functions could steal the > string [ or at least it's c_str() ] and thus avoid having to copy it. All > those copies quickly add up to a lot. > You can't steal the contents of a std::string without access to its internals, which only the standard library has. You can't steal the c_str() ... I'm not even sure what that would mean. ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: enums that are really just sets of constants
On 7 May 2017 at 15:10, Kjell Ahlstedt <kjellahlst...@gmail.com> wrote: > Den 2017-05-06 kl. 23:09, skrev Jonathan Wakely: > > On 6 May 2017 at 21:00, Murray Cumming <murr...@murrayc.com> wrote: > > The old style-enum won't let us change this, in gtkmm 3, > > Gtk::RESPONSE_OK > into this, in gtkmm 4: > Gtk::Dialog::Response::OK > without also polluting the API with this > Gtk::Dialog::OK > > Using an old-style enum would let us have this: > Gtk::Dialog::RESPONSE_OK, > (and Gtk::Dialog::Response::RESPONSE_OK) > which is still an improvement, but not quite as nice. > > Strictly speaking, an old-style enum *and* a scope would allow that. > > namespace Gtk { > struct Dialog { > struct Response { > enum ResponseEnum { OK }; > }; > }; > } > > That would give you the implicit conversions of old-style enums, but > still give scoped names. That might not be useful, I'm just saying > it's possible. > ___ > > That might very well be useful. A minor drawback is that we would have both > Gtk::Dialog::Response::OK (wanted) and > Gtk::Dialog::Response::ResponseEnum::OK (unwanted). With an unnamed > old-style enum there would be only Gtk::Dialog::Response::OK. > > namespace Gtk { > class Dialog : public ... { > public: > struct Response { > enum { OK }; > }; > }; > } > > An unnamed enum entails some restrictions, as discussed in > https://bugzilla.gnome.org/show_bug.cgi?id=86864#c34, but that's probably > not important for the very few enums in gtkmm and other mm-modules where we > want implicit conversion to int. Personally I find the downsides of unnamed enumerations types (can't overload on the type, don't have a name to refer to the constants even though they are allegedly related) are much worse than the fact there are two ways to refer to the enumerations. I've never seen problems arising from the fact that you could also write Gtk::Dialog::Dialog::Dialog::Dialog::Response::OK (because of the injected-class-name) so I don't see why the case you mentioned would be a real problem. If you're really worried about it: namespace Gtk { class Dialog : public ... { public: struct Response { enum ResponseEnum { }; static constexpr ResponseEnum OK = 0; static constexpr ResponseEnum ERR1 = 1; static constexpr ResponseEnum ERR2 = 2; }; }; } But I don't think that's an improvement. ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: enums that are really just sets of constants
On 6 May 2017 at 21:00, Murray Cummingwrote: > On Sat, 2017-05-06 at 18:08 +0100, Daniel Boles wrote: >> So it seems that the only option is to continue using C-style enums >> within classes, e.g. class Dialog { enum ResponseType{} } as >> present.. As someone already mentioned, I see no problem with this: >> such an enum is not inherently bad in itself; it's only bad if chosen >> in o s case where another solution (enum class, constexpr, etc.) is >> an available and more appropriate option. As that does not apply, the >> C-style enum should continue to serve this purpose well. > > The old style-enum won't let us change this, in gtkmm 3, > Gtk::RESPONSE_OK > into this, in gtkmm 4: > Gtk::Dialog::Response::OK > without also polluting the API with this > Gtk::Dialog::OK > > Using an old-style enum would let us have this: > Gtk::Dialog::RESPONSE_OK, > (and Gtk::Dialog::Response::RESPONSE_OK) > which is still an improvement, but not quite as nice. Strictly speaking, an old-style enum *and* a scope would allow that. namespace Gtk { struct Dialog { struct Response { enum ResponseEnum { OK }; }; }; } That would give you the implicit conversions of old-style enums, but still give scoped names. That might not be useful, I'm just saying it's possible. ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: enums that are really just sets of constants
On 22 April 2017 at 05:57, Dr. Diether Knof wrote: > Hello, > > for the integer wraps used for flags I have a third proposition, a working > example is attached: > * "enum class DisplayOption" for the individual flags > * "class DisplayOptions" with an implicit converter DisplayOption -> > DisplayOptions > So we get an enum for the single options and avoid the old enum-style. Why not have the constants declared inside the class, so you only have one name to remember, not DisplayOption and DisplayOptions? You can overload operator| and operator& for enums, so the only benefit to this seems to be the implicit conversion to bool (why not explciit?) ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: enums that are really just sets of constants
On 19 April 2017 at 11:51, Kjell Ahlstedt wrote: > Den 2017-04-19 kl. 12:24, skrev Murray Cumming: > > On Wed, 2017-04-19 at 10:30 +0100, Jonathan Wakely wrote: > > You can also use a namespace to give them their own scope, which has > less overhead than a class type (no RTTI for the class, no way for > users to create instances of the class type, or pointers to it, which > would have no purpose if it's just being used to create a new scope > for the enumerators). > > Good point. > > I'm leaning towards this at the moment. > > Is it possible to define a namespace within a class? No. ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: enums that are really just sets of constants
On 19 April 2017 at 09:37, Murray Cumming wrote: > In the ABI-breaking versions of glibmm and gtkmm, we have recently > changed the enums to be C++11 "enum class"s. This is generally a > welcome improvement. > - Their values are, for instance, Things::ONE, rather than THINGS_ONE. > - Their values do not convert implicitly to other types such as int or > bool, helping the compiler to find some programmer mistakes. > > We are also gradually moving the enums inside classes when they are > typically only used with that class. > > However, some of the C enums that we wrap are actually meant to be > integer constants, so it seems that we cannot and should not use "enum > class" for these. How are they used? Are they compared to integers? Are they passed to gtk APIs that expect integers? You can use scoped enums anyway, but you'd need an explicit cast to an integer, so it might not be appropriate. > So I wonder what is the most "modern C++" way to do > this while keeping the new-style syntax. Here are two possibilities: > > 1. Use old-style enums inside a class: > > class ResponseType { > public: > enum Enum { > NONE = -1, > REJECT = -2, > ACCEPT = -3, > ... > }; > }; You can also use a namespace to give them their own scope, which has less overhead than a class type (no RTTI for the class, no way for users to create instances of the class type, or pointers to it, which would have no purpose if it's just being used to create a new scope for the enumerators). > But shouldn't we just avoid old-style enums completely? Why? Both types still have uses in modern C++. Old doesn't mean bad. N.B. since C++11 you can use the enumeration type's name as a qualification even for unscoped (i.e. old-style, non-class) enums: enum E { Foo, Bar, Baz }; auto e = E::Foo; So you can use the new syntax even with old-style enums. The problem is that you're not *required* to do that, you can still just say Foo, so the names still leak into the surrounding scope. With a scoped (i.e. new-style, class) enum the qualification is required. > 2. Use constexpr int constants inside a class: > > class ResponseType { > public: > constexpr int NONE = -1; > constexpr int > REJECT = -2; > constexpr int ACCEPT = -3; > ... > }; > > But shouldn't we use some kind of enum to group the values together? Is their type actually important? i.e. are these different values of the same logical type? If yes, then using an enumeration makes sense. Otherwise just using an enumeration type to create an arbitrary group doesn't add any benefit. The example above looks like these are different values for the same "thing" so giving them the same type makes sense to me. It allows overloading on that type, for example. Aside: IMHO the shouty ALL_CAPS naming is not good style in C++, see https://accu.org/index.php/articles/1923 for my reasoning. ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: Supporting C++17
On 4 April 2017 at 23:37, Chris Vine wrote: > Aha, this may be it. > http://en.cppreference.com/w/cpp/language/noexcept_spec also says: > "Functions differing only in their exception specification cannot be > overloaded (just like the return type, exception specification is part > of function type, but not not part of the function signature) (since > C++17)." > > So I suspect that the noexcept specification may still not affect name > mangling. Right. See the foo and bar examples. You can't overload like this: void f() noexcept; void f(); But you can overload like this: void g(void(*)()); void g(void (*)() noexcept); The mangled name of a function doesn't depend on its exception specification. It does depend on the parameter types (as it always has in all versions of C++) and the parameter types can now be affected by exception specifications. ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: Supporting C++17
On 4 April 2017 at 23:28, Chris Vine <ch...@cvine.freeserve.co.uk> wrote: > On Tue, 4 Apr 2017 23:09:33 +0100 > Jonathan Wakely <gt...@kayari.org> wrote: >> On 4 April 2017 at 22:56, Chris Vine wrote: >> > I would check that. It didn't affect ABI in C++11/14, but I am not >> > so sure about C++17. According to >> > http://en.cppreference.com/w/cpp/language/noexcept_spec, >> > in C++17 "The noexcept-specification is a part of the function type >> > and may appear as part of any function declarator." If it is part >> > of the type then it might feature in name mangling, so this is >> > worth checking with the compiler writers. >> >> In C++17 the exception spec is part of the type, so noexcept(true) >> functions are mangled differently from functions that are >> noexcept(false). > > As I said in my follow-up email, on reflection I agree with you about > noexcept(false). > > But if this is correct about noexcept(true), and I am now beginning to > doubt myself on this, then it seems a recipe for broken libraries. It > makes any code with a noexcept(true) function specification which has > been compiled with the -std=c++14 option ABI incompatible with the same > code compiled with the -std=c++17 option. Not any code, only code that depends on the type of function pointers in mangled names. The mangled names of the functions themselves don't change, only names that depend on them. Using https://godbolt.org/g/akduU4 again, foo anr bar do not change their mangled names. But f2, which depends on decltype(), does change. However, it's uncommon to actually use decltype() like that in a function signature. Far more common would be something like: using func_type = void(*)(); void f2(func_type); And this wouldn't change, because func_type doesn't include the exception specification (because it wasn't allowed to in C++14). There's an implicit conversion from R(*)(Args...) noexcept to R(*)(Args...) so calling f2() would still work whether it's declared to take void(*)() or void(*)()noexcept. Some code may well be affected, and we don't know exactly how much, but it's not as catastrophic as you suggest. It's a good reason not to require C++17 for glibmm yet though :-) > What benefit accrues from making the noexcept specification part of > the type which is worth all that ABI breakage? See my previous email. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0012r1.html also gives some (terse) rationale. ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: Supporting C++17
On 4 April 2017 at 23:08, Chris Vine wrote: > On second thoughts, noexcept(true) might possibly change ABI in C++17, > but it seems inconceivable that noexcept(false) would. Right. You can verify this fairly easily: https://godbolt.org/g/akduU4 Notice that the type of foo (as used in the type of f1) is the same for c++98, c++14 and c++17. The type of bar (as it shown in the type of f2, which godbolt's demangler doesn't even support!) changes for c++17. foo is a noexcept(false) function, and is the same whether it uses throw(bad_cast) or noexcept(false). bar is a noexcept(true) function, and is the same whether it uses throw() or noexcept(true), but is not the same for c++17 comapred with earlier versions. But what makes a difference is -std=c++17, not whether you use throw(...) or noexcept(...). > It also seems > weird that merely applying -std=c++17 to your code should break its > ABI. The more I think about it, the less clear I am what making the > noexcept specification part of the function type in C++17 actually > involves compiler-wise, or what it achieves. It allows overloading on whether a function can throw, and specializing templates on it, and deducing it from template arguments. So if you take the address of a function you don't lose it's "noexceptiness". Previously this static assertion could never pass: void f() noexcept; template void g(F f) { static_assert( noexcept( f() ), "callback won't throw" ); } int main() { g( ); } In C++17 it compiles. ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: Supporting C++17
On 4 April 2017 at 22:56, Chris Vine wrote: > I would check that. It didn't affect ABI in C++11/14, but I am not so > sure about C++17. According to > http://en.cppreference.com/w/cpp/language/noexcept_spec, > in C++17 "The noexcept-specification is a part of the function type and > may appear as part of any function declarator." If it is part of the > type then it might feature in name mangling, so this is worth checking > with the compiler writers. In C++17 the exception spec is part of the type, so noexcept(true) functions are mangled differently from functions that are noexcept(false). But functions with dynamic exception specification aren't noexcept(true), so they're not mangled as noexcept(true) functions would be. If you replace the throw(std::bad_cast) with neoxcept(false) (or, equivalently, omit the exception specification entirely) they still aren't noexcept(true). Here's the proof: https://paste.fedoraproject.org/paste/Pwm-rv4LGXKh2EDVJSeOEl5M1UNdIGYhyRLivL9gydE=/ N.B. I didn't say that exception specifications don't affect the type, I said that removing the deprecated dynamic exception specification, i.e. throw(std::bad_cast), doesn't affect the type. Because it's still a noexcept(false) function. ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: Supporting C++17
On 4 April 2017 at 15:09, Jonathan Wakely wrote: > On 4 April 2017 at 14:52, Murray Cumming wrote: >> Noticed here: >> https://bugzilla.redhat.com/show_bug.cgi?id=1438766 From that bug report: (In reply to Murray Cumming from comment #6) > This makes sense: C++17 will remove support for old-style exception > specifications, so we'd need some cleverness to support both the old and new > ways in glibmm. I guess this will break lots of C++ code. Why try to support the old way? Dynamic exception specifications are not very useful, and have been recommended against for many many years. Simply removing them (so the functions are implicitly noexcept(false)) shouldn't break any code. Even if you have virtual functions using throw(X), user code that overrides them would still compile if you removed them: struct X { virtual void f() noexcept(false) { } }; struct Y : X { void f() throw(int) { } }; This is still OK, because the Y::f override has a stricter exception specification. The other way around doesn't work. If you have throw(std::bad_cast) on a virtual function then users who override it are forced to also use a deprecated dynamic exception specification, they can't use noexcept(false): struct X { virtual void f() throw(int) { } }; struct Y : X { void f() noexcept(false) { } }; v.cc:6:8: error: looser throw specifier for ‘virtual void Y::f() noexcept (false)’ void f() noexcept(false){ } ^ v.cc:2:16: error: overriding ‘virtual void X::f() throw (int)’ virtual void f() throw(int) { } ^ (I don't see any uses on virtual functions in glibmm or gtkmm so this might not be a problem anyway). Simply removing them from your headers seems the best solution. ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: Supporting C++17
On 4 April 2017 at 14:52, Murray Cumming wrote: > Any ideas about how we should support C++17 in gtkmm-3.0 without losing > C++11/14 compatibility and without breaking ABI? Replace all dynamic exception specifications with noexcept(false) (or just no exception specification). That's not an ABI change. > Or should we require C++17 for later gtkmm-3.0 versions? I think that would be premature, GCC support for it is still experimental. > Noticed here: > https://bugzilla.redhat.com/show_bug.cgi?id=1438766 ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: gtkmm 4: Glib::ustring: implicit conversions with streams
On 20 December 2016 at 09:26, Kjell Ahlstedt wrote: > > The conversions done by Glib::ustring are reasonable, at least if the read > or written stream uses the global locale. A std::locale contains a codecvt > facet, used for converting between one character encoding in the stream > (file) and a possibly different character encoding in main memory. But > Glib::ustring shall always contain UTF-8 encoded characters, independent of > the stream's locale and codecvt facet. It's reasonable that ustring's > operator<<() and operator>>() convert between UTF-8 and the stream's main > memory encoding. I get horribly confused by C++ locales, and especially the character encoding parts, but I think streams expect to receive characters in the native character set, so I think using the global locale is correct. That gives you a conversion from UTF-8 to the native character set, which gives you something in the encoding that streams expect. When a stream wants to perform a conversion using its imbued locale it already knows how to do that, e.g. std::filebuf does that so that bytes written to a file are converted from the in-memory encoding to the on-disk encoding. But as I said, I find this stuff very confusing. ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: Bug in documentation: Gio::File Class Reference
On 3 August 2016 at 23:38, Alwin Leerling wrote: > I believe I may have found some errors in the reference documentation > of the Gio::File Class: > > Function signatures > > std::string Gio::File::get_basename() const > std::string Gio::File::get_path() const > std::string Gio::File::get_relative_path( > const Glib::RefPtr< const File & descendant > > ) const > std::string Gio::File::get_uri() const > > are all declared returning a const std::string. No they aren't, those return non-const std::string objects. ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: Shouldn't Glib::ustring::raw() return const char* ?
On 2 August 2016 at 07:03, John Emmas wrote: > I just updated my compiler to VS2015 after using VS2005 for many years. I > built a small test app and linked it to my DLLs (which are still built with > the older compiler). Ultimately, they'll be getting built with the new > compiler and I was aware of some things to avoid (such as not allocating > memory in a DLL and trying to release it in the new app etc). But I didn't > anticipate the problem with std::string. Consider this example:- > > void some_func() > { > std::string test = Glib::get_application_name(); > } > > 'test' is a std::string in the format expected by VS2015 - whereas (in my > case) the call to 'get_application_name()' returns a std::string in the > format that was known to VS2005 - so calling that function from my new app > is guaranteed to crash my program. I figured that if I could obtain the > application name in a POD char array, that might help - and I quickly > discovered that this change seemed fix things:- > > std::string test = Glib::get_application_name().c_str(); > > but when I mentioned it on a popular programming forum, someone pointed > out that if the above was working, that was purely a case of luck. > Why is it purely a case of luck? Because get_application_name() returns a std::string by value, which tries to copy the VS2005 type using the code from VS2015? ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: Problem using std::prev on ustring iterator
On 18 March 2016 at 18:11, Jonathan Wakely <gt...@kayari.org> wrote: > On 18 March 2016 at 17:57, jeremy.harmon wrote: >> Hello, >> >> When I try to use std::prev on a ustring const_iterator nothing >> happens, operator-- works fine. >> >> Glib::ustring str = "test"; >> Glib::ustring::iterator iter = str.begin(); >> >> std::advance(iter); >> printf("%c\n", *iter); >> >> std::prev(iter); >> printf("%c\n", *iter); >> >> iter--; >> printf("%c\n", *iter); >> >> Output is >> e >> e >> t >> >> Any ideas why it doesn't work? > > Because unlike std::advance, std::prev doesn't modify its argument, it > returns the new iterator instead. > > http://en.cppreference.com/w/cpp/iterator/prev So, for completeness, you probably want to do this instead: iter = std::prev(iter); or std::advance(iter, -1) ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: Problem using std::prev on ustring iterator
On 18 March 2016 at 17:57, jeremy.harmon wrote: > Hello, > > When I try to use std::prev on a ustring const_iterator nothing > happens, operator-- works fine. > > Glib::ustring str = "test"; > Glib::ustring::iterator iter = str.begin(); > > std::advance(iter); > printf("%c\n", *iter); > > std::prev(iter); > printf("%c\n", *iter); > > iter--; > printf("%c\n", *iter); > > Output is > e > e > t > > Any ideas why it doesn't work? Because unlike std::advance, std::prev doesn't modify its argument, it returns the new iterator instead. http://en.cppreference.com/w/cpp/iterator/prev ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: Replace Gtk::manage() with std::unique_ptr<>?
On 08/02/16 10:18 +1300, Ian Martin wrote: As you've said, using unique_pointer mandates a design with only one access point to the controlled object, That's not true. std::unique_ptr mandates one *owner* of the object, but that doesn't prevent you accessing it through any number of non-owning pointers. The only caveat is that you must ensure that the object is still valid for as long as you use the non-owning pointers, i.e. there is still an owner keeping it alive. Otherwise your non-owning pointers become dangling and accessing the expired object is undefined behaviour. If you cannot guarantee that the owning pointer outlives the non-owning pointers then unique_ptr is not the right solution. Instead you can use std::shared_ptr as the owner (even if you only have a single owner) because that allows you to use std::weak_ptr as the non-owning observer. The benefit of std::weak_ptr is that you can (in fact, must) check whether there is still a shared_ptr that owns the object before you access it, so you can never access an expired object through a weak_ptr, instead you get an empty shared_ptr or an exception. That means there can be no dangling pointers that have undefined behaviour when dereferenced. ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: Replace Gtk::manage() with std::unique_ptr<>?
On 08/02/16 13:19 +0100, Murray Cumming wrote: On Mon, 2016-02-08 at 11:56 +, Jonathan Wakely wrote: [snip] A cleaner API would operate in terms of rvalues returned from functions, and passed straight into other functions, avoiding std::move entirely. [snip] Do you mean like this? window.add(create_button("something")); That's already possible by just taking a std::unique_ptr<> by value. Yes, but it doesn't give you a non-owning pointer which can be used to do other things to the button (either before or after adding it to the window) which is what the thread was about. Your proposed patch in Bugzilla has lots of TODO comments for use-after-move (which is undefined behaviour and crashes). What I'm saying is that those user-after-move need to be fixed by one of: (1) taking a raw pointer before transferring ownership by moving the unique_ptr, which you suggested at https://mail.gnome.org/archives/gtkmm-list/2016-February/msg00011.html (2) have the "add" functions return a raw pointer, as Diether suggested at https://mail.gnome.org/archives/gtkmm-list/2016-February/msg00014.html (3) add a helper that extracts a non-owning raw pointer as the rvalue passes by, as I suggested in https://mail.gnome.org/archives/gtkmm-list/2016-February/msg00018.html You said (1) "doesn't seem much better" than use-after-move, which I disagree with. It's infinitely better because it is not undefined and doesn't crash :-) But it's not ideal because it doesn't allow rvalues to be passed straight from factory functions to sinks. You must create an intermediate local variable, extract a raw pointer, then use std::move to cast back to an rvalue. Options (2) and (3) both allow rvalues to be passed straight from factories to sinks, but allow a non-owning pointer to be obtained at the same time. However, I wouldn't want to enforce that if it forced people to write code like this, without being able to break it up into separate lines: window.add( create_frame_with_children( create_label("something"), create_button("some button"))); It doesn't enforce anything. You always have the option of storing the returned objects in local variables and moving them in, if that's what you prefer. But if you prefer *not* to do that, so that you don't need to use std::move() and don't leave any empty unique_ptr objects lying around, then only options (2) and (3) allow you to do that. Option (1) enforces intermediate local variables. Options (2) and (3) allow the programmer to choose. ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: Replace Gtk::manage() with std::unique_ptr<>?
On 08/02/16 00:08 +0100, Murray Cumming wrote: On Sun, 2016-02-07 at 22:51 +0100, Dr. Diether Knof wrote: Hello, I think, to use std::unique_ptr and std::move instead of Gtk::manage is a good idea, but it is more difficult to use: > auto widget = std::make_unique("some button"); OK > notebook.append_page(std::move(widget), "something"); OK, but widget does no longer point to the botton, compare with the example at http://en.cppreference.com/w/cpp/utility/move > notebook.child_property_tab_expand(*widget) = true; Should lead to a segmentation fault. [snip] Yes, it does, and that's the issue here. (I've heard various discussions of what the C++ standard specifies about how valid or defined the moved-from object is, but I would indeed prefer to avoid any use after move.) It's not complicated, but it's often explained badly, or by people who don't know the rules. For any type defined in the C++ standard library (unless it specifies stronger guarantees) a moved-from object is in a *valid* but *unspecified* state. Valid but unspecified means it still maintains its invariants, but you can't assume anything more about its state. So you can't know if it's safe to call functions that have preconditions unless you first check that the preconditions are met. e.g. a moved-from std::string may or may not be empty, so doing s[4] may or may not be safe. However you can use any member functions that have no preconditions, so you can call s.size() to discover the string's state, and then it's safe to use s[4] if size() > 4. Some types offer stronger guarantees and std::unique_ptr is one of them. Obviously a type that models unique ownership has to stop owning its pointer after it transfers to another object, so std::unique_ptr is guaranteed to be null after it is moved from. So dereferencing it is undefined behaviour (typically resulting in a segfault). (In general the guarantees above are only true for types defined in the Standard Library. For non-standard types it is good style, and highly recommended, to follow at least the "valid but unspecified" guarantee for moved-from objects, with stronger guarantees for types like smart pointers where that makes sense. However in general class authors can define whatever semantics they want for their own types after they are moved from. So if a class author says that after being moved from her type can only be destroyed or assigned a new value, that's OK.) [snip] So, in order to create a widget, move it into a container and use it afterwards, we have to create two pointers (the unique-pointer and a normal pointer): > auto widget = std::make_unique("some button"); OK > Gtk::Widget* widget_to_expand = *widget; Wrong, right is: Gtk::Widget* widget_to_expand = widget.get(); > notebook.append_page(std::move(widget), "something"; OK This is a fairly typical idiom: get a raw (non-owning) pointer that will remain valid after ownership is transferred from the (owning) unique_ptr to something else. The owning pointer is unique, but the non-owning pointer is not, you can have as many non-owning observer pointers as you want. The downside of this approach is that you can't do: extern std::unique_ptr button_factory(const char*); notebook.append_page( button_factory("some button"), "something" ); i.e. you can't pass an rvalue straight to a function taking a std::unique_ptr, because you don't get a chance to take the raw pointer from it. So you need to create an lvalue, get a raw pointer, then cast back to an rvalue using std::move: auto button = button_factory("some button"); Button* raw = button.get(); notebook.append_page( std::move(button), "something" ); raw->blahblah(); This is more verbose and more error-prone because 'button' is left hanging around, containing null, tempting people to dereference it and get a segfault. Another idea is to change the add-methods to return a pointer to the object added. So the code can be written as (for clearity with Gtk::Button* instead of auto): Gtk::Button* button = container.add_unique(std::make_unique("a button")); For this, Container::add_unique() must be a (simple?) template, so it returns the exact type for the pointer (Gtk::Button*) and not Gtk::Widget*: template X* Container::add_unique(std::unique_ptr(X) widget) { X* p = widget.get(); this->add(std::move(widget)); return p; } virtual void Container::add(std::unique_ptr widget); [snip] This is nicer, because you can pass an rvalue straight in, but still get a raw pointer: Button* button = c.add_unique( button_factory("some button") ); This style avoids needing any explicit std::move() to cast the std::unique_ptr back to an rvalue, and doesn't leave any null object hanging around. Yes, I've considered this, but I'm still hoping for something nicer. The suggestion above looks fine to me. Certainly better than a segfault :-) I think I'd be content with needing a call to a getter method after a std::move(). I think that would make
Re: Replace Gtk::manage() with std::unique_ptr<>?
On 08/02/16 15:40 +0100, Murray Cumming wrote: On Mon, 2016-02-08 at 12:40 +, Jonathan Wakely wrote: [snip] You said (1) "doesn't seem much better" than use-after-move, which I disagree with. It's infinitely better because it is not undefined and doesn't crash :-) Of course. I don't want code that looks wrong and crashes. Sorry for the confusion caused by my choice of words. But it's not ideal because it doesn't allow rvalues to be passed straight from factory functions to sinks. You must create an intermediate local variable, extract a raw pointer, then use std::move to cast back to an rvalue. Options (2) and (3) both allow rvalues to be passed straight from factories to sinks, but allow a non-owning pointer to be obtained at the same time. [snip] Ah, now I see your point. Thanks. I do find your suggested API awkward (I've renamed add_unique() to add()): I agree, it's not ideal, so I hope there's still a better solution waiting to be found. Button* b = nullptr; //I don't like this being even momentarily uninitialized. murrayc. c.add(pass_and_observe(button_factory("some button"), b)); b->blahblah(); However, it's just one pass_and_observe() template that works on top of the simple add(unique_ptr<>) overloads. People could use it they wanted to, or use a get_child() method if they preferred, trying to leave an explicit std::move() as late as possible so they didn't need to. I hope we can improve the occasional API that makes this difficult currently. By the way, would you want people to use this even without a factory method? For instance: Button* b = nullptr; //I don't like this being even momentarily uninitialized. murrayc. Yep, fair enough :-) c.add(pass_and_observe(std::make_unique("some button"), b)); b->blahblah(); Could do. I guess it depends on how much gtkmm devs (which I'm not!) would want to avoid using std::move() and leaving null lvalues around. That's not necessarily a bad thing, but is a potential source of use-after-move bugs. I've seen it suggested that any explicit use of std::move is a code smell because of those potential bugs (I'm not sure I entirely agree, but can see their point). ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: Replace Gtk::manage() with std::unique_ptr<>?
On 08/02/16 15:56 +0100, Murray Cumming wrote: On Mon, 2016-02-08 at 15:44 +0100, Krzesimir Nowak wrote: Just a minor hint here - Button* b {}; should do the trick and it is not that lot more of typing. Thanks. Whether we should now use curly brackets for "uniform initialization" wherever possible is a whole other question we should discuss eventually. It looks odd to me, but I accept that that's no reason not to like it. I expect to get used to it. Personally I continue using "= nullptr" for pointers. Uniform init is great for generic code as it works for anything default constructible, and great in many other situations, but to initialize a pointer to null I think "= nullptr" is as clear and explicit as you can get. But I'm not a gtkmm dev or even a gtkmm user, and YMMV :-) ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list