- auto& - 3 Updates
- Const on pass-by-value formal args - 1 Update
- RAII design question - 3 Updates
- MinGW g++ encoding `u8"literal"` with Windows ANSI Western, not UTF-8 - 1 Update
Gareth Owen <gwowen@gmail.com>: Jun 12 09:47PM +0100 > auto c = v[0]; > auto& r = v[0] > c is a char; to get a reference I must explicitly say so. As a rationale, I'd say i) principle of least surprise ii) because if a function returns a reference, then auto couldn't be used to declare a non-reference variable, which would make it a hell of a lot less useful. There's no syntax for "concrete type for referred to by reference on RHS" std::vector<int> a; // ... initialize ... auto val = a[3]; // most of the time I probably don't want val to be a reference here val += ... ; // don't want a[3] to change. |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jun 12 11:46PM +0200 On 12-Jun-17 10:28 PM, Vir Campestris wrote: > Why is it that when I call a function that returns a reference, and > assign the result to an auto, it copies the value rather than declaring > the auto as a reference? I think Gareth Owen, in his reply, gave a good/likely possibility for the rationale, namely the principle of least surprise. But re the technical, you can view `auto` as `decltype` + `std::decay`. Here are `std::decay<T>` rules quoted from cppreference.com: • If T names the type "array of U" or "reference to array of U", the member typedef type is U*. • Otherwise, if T is a function type F or a reference thereto, the member typedef type is std::add_pointer<F>::type. • Otherwise, the member typedef type is std::remove_cv<std::remove_reference<T>::type>::type. So, array-ness, function-ness, const-ness, volatile-ness and reference-ness are removed. > auto c = v[0]; > auto& r = v[0] > c is a char; to get a reference I must explicitly say so. My main `auto` annoyance is that instead of const ptr_<auto> p = foo(); … I must write something like const auto p = pointer_result( foo() ); … to explicitly indicate the expected pointer-ness of the foo() result, or else I'd have to use the operator notation; i.e., that `auto` is by far not as powerful as template function argument deduction. :( Cheers!, - Alf |
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jun 13 12:20AM +0100 Thems is the rules. auto mimics template type deduction, and discards references and const (and volatile) qualifiers. If you want the reference or cv qualifier to be detected, use decltype(auto), which uses decltype type deduction rules. (For completeness, you were initializing not assigning. Initializing a value type copies.) Chris -------------------------- On Mon, 12 Jun 2017 21:28:43 +0100 |
ram@zedat.fu-berlin.de (Stefan Ram): Jun 12 10:57PM >My personal preference is to have top level `const`-s on definition >only, because that's where they have an advantage, while in the pure >declaration they're negative value noise. I want a pure declaration (i.e., a not-defining declaration) to be a "prototype" that can double as a part of the documentation of the "interface" of a function. The const-ness of a parameter is /not/ a part of the interface of a function, but of it's implementation. So it belongs into the definition, but not into a pure declaration. A hypothetical language might even allow to add the const qualifier of a parameters within the /body/ of the definition, separating the regions of the source code into a region for the interface and a region for the implementation: int f( int x ) /* interface */ { const x; return 2 * x; } /* implementation */ Of course, in the case of int f( int const * const x ) ~~~ , the first »const« /is/ part of the interface. |
Gareth Owen <gwowen@gmail.com>: Jun 12 09:59PM +0100 I had a timer class that measure the duration of its own existence. In Semi-Pseudo code it looked like this. typedef long long Time; class Timer { private: Time start_time; Time& total_time; } Timer::Timer(Time& tot) : start_time(gettimeofday()), total_time(tot) { } Timer::~Timer() { end_time = gettimeofday(); total_time += end_time - start_time; } So I wanted to extend the CancellableTimer : public Timer { private: bool canceled; public: // if I call obj.cancel() then the destructor should // not void cancel(void) { canceled = true;} } Now, it seems to me that I can't get the derived class behaviour without modifying the base class, because the base destructor always runs. But it also seems that by Liskov Substitution Principle, a CancellableTimer IS A Timer, so it'd be nice if I could extend Timer in this way. What am I missing? |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jun 13 12:06AM +0200 On 12-Jun-17 10:59 PM, Gareth Owen wrote: > CancellableTimer IS A Timer, so it'd be nice if I could extend Timer in > this way. > What am I missing? Well, the Liskov substitution applies to instances of types, not to types themselves. Or in other words, the LSP is about the behavior of objects between their creation and destruction, not including what happens before the object's constructor has finished, or after its destructor has begun execution. For example, a derived class can conform to the LSP wrt. a public base class, but require different constructor arguments – that's OK, because it's not within the domain of the LSP. But you are interested in what happens during destruction. If a `Timer` has no behavior between the lifetime endpoints then the solution simple: an is-a relationship is then meaningless, so don't derive. I see no way to make the class derivation work without essentially duplicating the CancellableTimer functionality up in base class Timer, which would be meaningless except as a way to restrict the interface of Timer. Without class derivation, if you're happy with just wrapping an instance of `Timer`, you can use dynamic or in-place allocation, and cancel it by just not destroying the instance. For the dynamic allocation that would leak memory, but you could preallocate say storage for 10 000 of them and say OK, that's the implementation limit. With C++11 and later, however, in-place allocation is not complex: there is alignment support. Cheers & hth., - Alf |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jun 13 12:22AM +0200 On 13-Jun-17 12:06 AM, Alf P. Steinbach wrote: >> end_time = gettimeofday(); >> total_time += end_time - start_time; >> } [snip] > leak memory, but you could preallocate say storage for 10 000 of them > and say OK, that's the implementation limit. With C++11 and later, > however, in-place allocation is not complex: there is alignment support. Sorry for that suggestion, it was dumb. It applies to the general problem of preventing destructor execution, but that's not what you need: it wouldn't even solve the problem. The obvious (to you and others, but not me some little time ago) solution is to let `CancellableTimer` just supply a different `Time` variable to the `Timer` instance. Cheers!, - Alf [looking for a brick wall to bang head against] |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jun 13 12:13AM +0200 On 06-Jun-17 3:13 AM, Manfred wrote: >> is a good idea anyway, but is difficult to guarantee with lots of >> editors that still prefer other encodings. > This is a problem only if the standard headers use non-ascii chars. No, it's a general problem. Consider UTF-16. ASCII text interpreted as UTF-16 = a lot of gobbledygook, and possibly even invalid sequences. Cheers!, & thanks for your suggestions else-thread, - Alf |
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