Monday, January 25, 2016

Digest for comp.lang.c++@googlegroups.com - 25 updates in 4 topics

Luca Risolia <luca.risolia@linux-projects.org>: Jan 25 01:28AM +0100

Il 24/01/2016 22:11, Jorgen Grahn ha scritto:
 
> What's wrong with std::swap(v[0], v[1]) ?
 
This is better:
 
using std::swap;
swap(v[0], v[1]);
 
as it does not disable ADL, which is the general advice in the STL.
Paul <pepstein5@gmail.com>: Jan 25 12:11AM -0800

On Monday, January 25, 2016 at 12:28:41 AM UTC, Luca Risolia wrote:
 
> using std::swap;
> swap(v[0], v[1]);
 
> as it does not disable ADL, which is the general advice in the STL.
 
I don't understand why using std::swap is better. Can you expand please? Thanks.
 
Paul
Luca Risolia <luca.risolia@linux-projects.org>: Jan 25 09:50AM +0100

On 25/01/2016 09:11, Paul wrote:
 
>> using std::swap;
>> swap(v[0], v[1]);
 
> I don't understand why using std::swap is better. Can you expand please? Thanks.
 
"std::swap may be specialized in namespace std for user-defined types,
but such specializations are not found by ADL (the namespace std is not
the associated namespace for the user-defined type). The expected way to
make a user-defined type swappable is to provide a non-member function
swap in the same namespace as the type" (cppreference.com)
 
"std::swap(v[0], v[1])" is a scope-qualified call, so it disables ADL,
while the "swap(v[0], v[1])" does not, as it is not a scope-qualified call.
 
For example:
 
namespace X {
struct Y {};
void swap(Y&, Y&) {
std::cout << "my swap\n";
}
}
 
int main() {
X::Y a, b;
 
std::swap(a, b); // X::swap() is ignored
 
using std::swap;
swap(a, b); // X::swap() is used
}
Paavo Helde <myfirstname@osa.pri.ee>: Jan 25 10:54AM +0200

On 25.01.2016 10:11, Paul wrote:
>> swap(v[0], v[1]);
 
>> as it does not disable ADL, which is the general advice in the STL.
 
> I don't understand why using std::swap is better. Can you expand please? Thanks.
 
The above specifically *avoids* using std::swap if there is a specific
swap() function present for elements of v.
 
See e.g. http://en.cppreference.com/w/cpp/language/adl, especially the
Notes section.
Paul <pepstein5@gmail.com>: Jan 25 01:02AM -0800

On Monday, January 25, 2016 at 8:51:17 AM UTC, Luca Risolia wrote:
 
> using std::swap;
> swap(a, b); // X::swap() is used
> }
 
Thanks to everyone on this thread. I understand the issues, both with regard to my original question and my follow-up about ADL.
 
Paul
Paavo Helde <myfirstname@osa.pri.ee>: Jan 25 11:07AM +0200

On 25.01.2016 10:54, Paavo Helde wrote:
>> please? Thanks.
 
> The above specifically *avoids* using std::swap if there is a specific
> swap() function present for elements of v.
 
Yep, to avoid using std::swap() one must say 'using std::swap()'.
Welcome to C++! Reminds me the 'throw()' declaration.
Juha Nieminen <nospam@thanks.invalid>: Jan 25 09:25AM

>> > copying.
 
>> What's wrong with std::swap(v[0], v[1]) ?
 
> Nothing. But I want to write the swap myself.
 
Why? If the type is move-constructible and move-assignable, std::swap()
will automatically move them rather than copy them.
 
--- news://freenews.netfront.net/ - complaints: news@netfront.net ---
SG <s.gesemann@gmail.com>: Jan 25 03:46AM -0800

On Sunday, January 24, 2016 at 10:03:52 PM UTC+1, Paul wrote:
> Suppose we want to swap the first two elements of a vector<T>
> Suppose further that the type T is very large so we want to avoid
> copying.
 
What kind of size are we talking about? sizeof(T)? Or size in terms
of how costly copying would be? The sizeof() a vector is rather small
(just three pointers) but copying a vector might involve copying lots
of other things that are not *directly* part of the vector.
 
> We can do
> T temp = v[0]; v[0] = v[1]; v[1] = temp;
> However, this seems to involve unnecessary copying.
 
You should do
 
using std::swap; // fall back on std::swap
swap(v[0], v[1]); // might invoke another swap via ADL
 
instead because it might resolve to a special swap function that has
been optimized for the type T (via ADL or a specialized std::swap).
std::swap's default implementation also makes use of move semantics:
 
template<class T>
void swap(T& a, T& b) noexcept(...) {
T t = std::move(a); // tries to move a into t
a = std::move(b); // tries to move b into a
b = std::move(t); // tries to move t into b
}
 
which is obviously better if T has a move constructor and move
assignment operator that is more efficient that their respective
copy versions.
 
> I therefore suggested that, for an operation that involves a lot of
> swapping (for example, a sort), we should use a vector of pointers
> to T rather than a vector<T> and swap via the pointers.
 
Yeah, if sizeof(T) is huge, this indirection might help. I would also
suggest to test this approach (std::vector<unique_ptr<T>> or boost::
ptr_vector<T>). If your T is a vector or a string, for example, this
is however not the case.
 
> the person) told me that T temp = v[0]; v[0] = v[1]; v[1] = temp;
> does not in fact move large objects around, and only moves pointers,
> so that my issue doesn't really exist.
 
First of all, it does not move anything because you didn't ask for it.
That's what std::move is for.
 
T temp = v[0]; // this *copies* v[0] to temp
 
There are situations where std::move is not necessary and in those
situations using std::move is actually somewhat harmful (since it
disables the otherwise applicable copy elision optimizations) but this
is not one of them, so you need to use std::move here.
 
But then it also depends on what T is and goes back to my first
question. If T is something like a std::vector<U> then you *don't*
need this additional layer of indirection because a vector *already*
stores its "elements" indirectly and has very efficient move
operations. These move operations are doing the pointer
manipulations. If sizeof(T) is huge, this is another story.
 
Cheers!
sg
"Öö Tiib" <ootiib@hot.ee>: Jan 25 04:19AM -0800

On Monday, 25 January 2016 10:51:17 UTC+2, Luca Risolia wrote:
 
> using std::swap;
> swap(a, b); // X::swap() is used
> }
 
That example is so but OP case is different. There are no 'a' and 'b'
but 'v[0]' and 'v[1]' that are of type 'std::vector<X::Y>::reference'.
So the story must be is (or isn't?) somewhat trickier?
SG <s.gesemann@gmail.com>: Jan 25 05:58AM -0800

On Monday, January 25, 2016 at 1:19:51 PM UTC+1, Öö Tiib wrote:
 
> That example is so but OP case is different. There are no 'a' and 'b'
> but 'v[0]' and 'v[1]' that are of type 'std::vector<X::Y>::reference'.
 
If v is a std::vector<T> where T != bool then v[0] and v[1] are lvalue
expressions of type T. Let's ignore the T==bool case here, OK?
 
> So the story must be is (or isn't?) somewhat trickier?
 
No. It's not trickier. Given
 
T a = ...;
T b = ...;
std::vector<T> v = ...;
 
there is no difference between the expressions a and v[0] with respect
to their type (T) and value category (lvalue).
 
using std::swap;
swap(a, b);
swap(v[0], v[1]); // works just as well as above
// if v contains at least two elements. :-)
 
There is a difference if you use decltype but that's because decltype
distinguishes between multiple cases and can look "beyond" the
expression. IIRC decltype basically distinguishes between three
cases:
 
* the declared type of some entity.
Example: decltype(a) is T
 
* the declared return type of a function.
Example: decltype(v[0]) is T&
Example: decltype(std::move(a)) is T&&
 
* The type and "lvalueness" of an arbitrary expression. You can
force this case with an additional set of parentheses around the
expression.
Example: decltype((a)) is T&
Example: decltype((v[0])) is T&
Example: decltype((std::move(a))) is T
In all cases the type of the expression is T. But only in the
first two cases they are lvalue expressions which is why you
get an lvalue reference type. Xvalues are basically ignored
in this case.
 
Isn't this nicely complicated? Exactly what you would expect from C++!
;-)
 
Cheers!
sg
Luca Risolia <luca.risolia@linux-projects.org>: Jan 25 03:36PM +0100

On 25/01/2016 13:19, Öö Tiib wrote:
> but 'v[0]' and 'v[1]' that are of type
> 'std::vector<X::Y>::reference'. So the story must be is (or isn't?)
> somewhat trickier?
 
The OP said elsewhere - before my answer:
 
"[...] But I want to write the swap myself."
 
He wants to write a swap for his type T.
 
Usually you want to declare swap in the same namespace as T, and the
typical advice to do make use of it is what I mentioned before.
 
Another conceptually similar and more familiar example in the standard -
which works because of ADL - is about operator<<(std::ostream&, T)
taking user-defined types as right hand argument. It's desiderable to
declare both your operator<< and T in the same namespace, e.g.:
 
namespace X {
struct T {};
std::ostream& operator<<(std::ostream&, const T& t);
}
 
int main() {
X::T t;
std::cout << t; // ADL
}
"Öö Tiib" <ootiib@hot.ee>: Jan 25 08:59AM -0800

On Monday, 25 January 2016 16:36:51 UTC+2, Luca Risolia wrote:
 
> He wants to write a swap for his type T.
 
> Usually you want to declare swap in the same namespace as T, and the
> typical advice to do make use of it is what I mentioned before.
 
Ok, I think I get it now, it is for case when he wants but is unsure
if he writes 'void swap(Y&, Y&)' in his namespace X?
So the 'using namespace std' serves as way to fall back to 'std::swap'
if he for some reason did not write 'X::swap' despite he said he wants.
 
Same fallback (without 'using namespace std' needed) works with
'std::iter_swap':
 
std::iter_swap(&a, &b); // X::swap() is used if it exists otherwise std::swap()
 
It may be someone considers it worse to read that way but code seems
to be is generated as good.

> X::T t;
> std::cout << t; // ADL
> }
 
The 'std::ostream' is used rarely lately ... 'swap' is more common. Also
here are no need for that 'using namespace std'.
"Öö Tiib" <ootiib@hot.ee>: Jan 25 09:13AM -0800

On Monday, 25 January 2016 15:59:14 UTC+2, SG wrote:
> swap(a, b);
> swap(v[0], v[1]); // works just as well as above
> // if v contains at least two elements. :-)
 
Ok. Got it.
 
> in this case.
 
> Isn't this nicely complicated? Exactly what you would expect from C++!
> ;-)
 
Indeed. Sometimes I wish that there were no references whatsoever
and considering if things are moved, copied or passed by reference
was decided by compiler somehow (like it works with "by-value"
return values). However it is sort of hard to come out with good clear
recipe to it.
JiiPee <no@notvalid.com>: Jan 24 11:53PM

On 24/01/2016 20:58, Vir Campestris wrote:
 
> While C syntax is a mess I don't think we can call it failed. I'm
> still writing it, 40 odd years later... though it does feel very
> painful knowing C++ is available.
 
C was definitely top language in its time, 70-80 early (that would have
been my choice in 70 s, early 80 s). But I think C++ is then better,
especially the latest version.
Robert Wessel <robertwessel2@yahoo.com>: Jan 25 03:46AM -0600

On 25 Jan 2016 04:26:51 GMT, ram@zedat.fu-berlin.de (Stefan Ram)
wrote:
 
> first to do this?) I am teaching C to beginners, and so far
> no one has complained about the syntax. So both experts and
> beginners embrace braces.
 
 
C may be the first. BCPL used $( and $) (two character
sequences), and of course other languages did things like begin..end
much earlier. Some of that may simply be due to the character set
limitations of the era - before 1969 many machines simply didn't have
the curly braces available in a convenient way (and it certainly
wasn't universal for a long time after that - arguably not even now).
 
OTOH, languages like Lisp used parenthesis a lot, often for similar
block-structuring purposes.
SG <s.gesemann@gmail.com>: Jan 25 02:34AM -0800

On Saturday, January 23, 2016 at 2:55:43 AM UTC+1, JiiPee wrote:
> In this thread/post you can tell what you like in C++11/C++14. How it
> made things nicer, how you use it and how it made those things easier.
> Why you like C++11/C++14 more than the old C++?
 
Apart from the obvious cool things (rvalue references, variadic
templates), I've just started to let go of classes and constructors to
some extent. For simple data-holding types I just use structs and
brace initialization:
 
struct foo {
double thiz;
std::string that;
};
 
void sink(foo);
 
foo source() {
return { 3.14159265, "pi" }; // Yay!
}
 
int main() {
sink({ 2.718281828, "e" }); // Yay!
}
 
The fact that I've been toying around with the Rust language probably
has something to do with this style. :)
 
I also like all the <type_traits> stuff. It's a stepping stone towards
concepts.
 
What I'm probably not appreciating enough right now is constexpr. I
know that constexpr functions were quite limited in C++11 but AFAIK
this has changed in C++14. But I don't really know its limitations
right now and what good things you can achieve using it.
 
Cheers!
sg
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jan 25 01:18PM +0100

On 1/25/2016 5:26 AM, Stefan Ram wrote:
> invents a new language, it is very probable that compound
> statements will start with a brace. (Which language was the
> first to do this?)
 
Whether to use braces or begin/end keywords is not part of the
syntactical /structure/, which is what "syntax" refers to here.
 
One way to see that the form is irrelevant is by defining "begin"/"end"
macros and thus change the surface appearance of your code.
 
The block structure itself is, however, a part of the syntactical
structure. But it is a very successful, not a failed, part. It was
[1]introduced in Algol. C was based on BCPL, which as I recall had round
parenthesis blocks (today the Windows batch file language is one example
of a language with round parenthesis blocks). The block and control
structure of BCPL was based on CPL. Possibly CPLs variant was based
directly on Algol.
 
 
> I am teaching C to beginners, and so far
> no one has complained about the syntax.
 
It may be that these beginners do not know enough to judge it.
 
There are also other possible explanations of the lack of criticism.
 
 
> So both experts and beginners embrace braces.
 
Braces are not a problematic part, and as braces (as opposed to using
other block markers) they're not part of syntactic structure.
 
I referred to the language designers' very informed expert opinions of
their own syntax creations, in particular the declaration syntax. It may
be that I was wrong about exactly which C creator, I shouldn't so
casually have written Kernighan, but it's easy enough to google up
references where Bjarne Stroustrup, the C++ language creator, states
this, which he's done one several occasions. E.g. in [1]an interview
with the C User's Journal in 1996, Bjarne stated that "I consider the C
declaration syntax an experiment that failed".
 
Surely the language creator must be considered an expert.
 
For that matter, I've been referred to as an expert.
 
But, by stressing that, I'm responding to what I perceive as the
associative impact of what you wrote. As far as I know it's not the case
that any experts are strongly opposed to curly braces or consider them a
failure. The braces, as braces, are just irrelevant here.
 
 
Cheers & hth.,
 
- Alf
 
Notes:
[1] <url: https://en.wikipedia.org/wiki/Block_%28programming%29#History>
[2] <url: http://www.stroustrup.com/cuj_interview.html>
Jerry Stuckle <jstucklex@attglobal.net>: Jan 25 09:43AM -0500

On 1/25/2016 7:18 AM, Alf P. Steinbach wrote:
>> no one has complained about the syntax.
 
> It may be that these beginners do not know enough to judge it.
 
> There are also other possible explanations of the lack of criticism.
 
I also have taught introductory C and C++ courses. These were to both
new and experienced programmers in corporate environments. None of them
had any criticism about the syntax, either. They accepted it and moved on.
 
 
>> So both experts and beginners embrace braces.
 
> Braces are not a problematic part, and as braces (as opposed to using
> other block markers) they're not part of syntactic structure.
 
How can you claim they are not part of the syntactic structure? They
are a major part of it.
 
> with the C User's Journal in 1996, Bjarne stated that "I consider the C
> declaration syntax an experiment that failed".
 
> Surely the language creator must be considered an expert.
 
BJarne Stroustrup did not create C.
 
> For that matter, I've been referred to as an expert.
 
Anyone can be referred to as an expert by others. I have been referred
to as an expert by many of my students. That does not make me one. It
only means I knew more than they did.
 
 
--
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jan 25 04:27PM +0100

On 1/25/2016 3:43 PM, Jerry Stuckle wrote:
 
> I also have taught introductory C and C++ courses. These were to both
> new and experienced programmers in corporate environments. None of them
> had any criticism about the syntax, either. They accepted it and moved on.
 
Not sure what you're talking about, it doesn't seem relevant to the
context (quoted above).
 
But if this is, like, from your point of view, a thread about what each
of us has done, I've taught C++ at college level, 20+ years ago, at then
Bodø College of Economics (now the University of Nordland) and to some
extent later at the corporate level. However, at the corporate level it
was mostly Java, which I didn't even know very much of at the time - but
the focus was not so much on the language. I helped (or mainly) create a
course for new employees in Andersen Consulting, now Accenture, called
"BEST", which was short for "Building Enterprise Solutions and Testing".
The nice thing about it was that it was first held in Nice, France. So I
got a sort of paid holiday. :)
 
 
>> other block markers) they're not part of syntactic structure.
 
> How can you claim they are not part of the syntactic structure? They
> are a major part of it.
 
It seems that you're missing the points entirely (wilfully?).
 
Namely, first that braces as such are not part of the structure, they
are arbitrary symbol choices; and secondly, that the block structure is
not a failure; and third, that it didn't stem from C but from Algol.
 
 
[snip]
>> Surely the language creator must be considered an expert.
 
> BJarne Stroustrup did not create C.
 
To me that's completely mal-apropos. Bjarne did not head the Toyota
corporation, either. For example. Are you seriously contending that
Bjarne, creator of C++, did not know [2]what he was talking about in
1996? Jeez.
 
 
[snip]
> Anyone can be referred to as an expert by others. I have been referred
> to as an expert by many of my students. That does not make me one. It
> only means I knew more than they did.
 
Oh well.
 
 
>> Notes:
>> [1] <url: https://en.wikipedia.org/wiki/Block_%28programming%29#History>
>> [2] <url: http://www.stroustrup.com/cuj_interview.html>
 
 
Cheers & hth., even though I couldn't make much sense of what you wrote,
 
- Alf
Juha Nieminen <nospam@thanks.invalid>: Jan 25 09:16AM


> I probably use 'auto' more than you do at this point, but I can easily
> imagine a future where some people write code which others (like me)
> reject as unreadable. As if we're not our own worst enemies already ...
 
Use 'auto' when it actually serves a useful purpose (eg. in generic code),
or when it's actually useful in some other way. Use it to save typing only
in rare, very specific circumstances (eg. with iterators, or in some
range-based for loops).
 
In normal usage, however, the only thing that 'auto' does is to circumvent
the strong typing system, which isn't always a good thing.
 
--- news://freenews.netfront.net/ - complaints: news@netfront.net ---
Jorgen Grahn <grahn+nntp@snipabacken.se>: Jan 25 02:21PM

On Mon, 2016-01-25, Juha Nieminen wrote:
> or when it's actually useful in some other way. Use it to save typing only
> in rare, very specific circumstances (eg. with iterators, or in some
> range-based for loops).
 
Happily, I think people agree so far ...
 
> In normal usage, however, the only thing that 'auto' does is to circumvent
> the strong typing system, which isn't always a good thing.
 
You should probably clarify that last part ... typing is still strong
if you use 'auto', so I think you really want to describe some other
problem.
 
C++ with auto is (it seems to me) more like type inference in languages
like Standard ML or Haskell, not like duck typing in Python. There /is/
a real type behind the 'auto' -- the only issue is if the reader gets enough
useful information about it, without seeing it spelled out.
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jan 25 03:36PM +0100

On 1/25/2016 3:21 PM, Jorgen Grahn wrote:
 
> C++ with auto is (it seems to me) more like type inference in languages
> like Standard ML or Haskell, not like duck typing in Python.
 
C# "var" comes to mind.
 
https://msdn.microsoft.com/en-us/library/bb383973.aspx
 
 
Cheers,
 
- Alf
David Brown <david.brown@hesbynett.no>: Jan 25 03:56PM +0100

On 25/01/16 15:21, Jorgen Grahn wrote:
> like Standard ML or Haskell, not like duck typing in Python. There /is/
> a real type behind the 'auto' -- the only issue is if the reader gets enough
> useful information about it, without seeing it spelled out.
 
Python also has strong typing. A key difference between "auto" in C++
and Python is that in C++, with "auto x = foo()", /x/ is the object with
the fixed type. In Python, with "y = foo()", /y/ is an identifier bound
to a nameless object with fixed type. y can be re-bound to any other
object of any type, unlike x.
 
"Duck typing" refers more to how types are classified. In C++, classes
are organised by inheritances - you can use an object in a particular
way if it or one of its ancestors is of a particular type. In Python,
you can use an object in a particular way if it has the appropriate
member. Python duck typing is more akin to templates in C++.
 
C++11 gives you much of the convenience of Python (by using auto rather
than spelling out the type every time), while retaining the safety of
static type checking in C++. Note that this is not about "strong
typing" or "type safety", as Python has these - it is about static or
compile-time checking of types rather than at run-time.
ram@zedat.fu-berlin.de (Stefan Ram): Jan 25 04:26AM

>learner up-front with the (according to Kernighan and Stroustrup) failed
>syntax experiment of C and early C++, which can be a barrier.
 
What specific production(s) do you refer to?
 
The most TIOBE-popular languages are: Java, C, C++, and C#.
All based on the C syntax which insofar has prevailed in the
evolution of languages. Even when today, in 2016, someone
invents a new language, it is very probable that compound
statements will start with a brace. (Which language was the
first to do this?) I am teaching C to beginners, and so far
no one has complained about the syntax. So both experts and
beginners embrace braces.
bleachbot <bleachbot@httrack.com>: Jan 22 08:02PM +0100

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: