Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Re: Copy-initialization

148 views
Skip to first unread message

Alf P. Steinbach

unread,
Sep 12, 2016, 3:08:02 AM9/12/16
to
On 12.09.2016 03:01, Stefan Ram wrote:
> I once had the idea of using direct-list-initialization
> whenever possible since it is using the "uniform initialization
> syntax", so it would be easy and tidy to use the same
> notation whenever possible.

Not quite the same. E.g. `std::string s{5, 'x'};` does not mean the same
as `std::string s(5, 'x');`. It's difficult (impossible?) to express the
latter with direct initialization with braces.


> But now I became aware of this idea:
>
> Explicit conversions are not used for copy-initialization.

Right.


> Since explicit conversions are deemed to be somewhat
> "dangerous" or "risky",

By whom?


> they should be avoided unless the programmer is sure that he wants them.

Hm.


> So, it would be better to use copy-initialization as often
> as possible because this has the effect of avoiding the
> "dangerous" explicit conversions?

They're not dangerous, they're just undesirable as implicit conversions.


Cheers & hth.,

- Alf

Alf P. Steinbach

unread,
Sep 12, 2016, 9:00:51 AM9/12/16
to
On 12.09.2016 12:38, Stefan Ram wrote:
> "Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
>>> Since explicit conversions are deemed to be somewhat
>>> "dangerous" or "risky",
>> By whom?
>
> It can be dangerous if they happen unintendedly, therefore
> they are made "explicit".
>
>> They're not dangerous, they're just undesirable as implicit conversions.
>
> So, sometimes
>
> T x{ e };
>
> and
>
> T x = e;
>
> both are possible and have the same effective semantics.
> Which do you choose then and why?

I prefer the "=" notation because it stands out visually.

• • •

If `T`is `U const` then I write that as

auto const x = U( e );

And I also use `auto` when the right hand side is named cast notation
(mention of the type), or where `explicit` constructors necessitate it.

• • •

As a concrete example, consider

#include <stdexcept>
using namespace std;

auto main() -> int
{
logic_error a{ "ah!" };
auto b = logic_error{ "bah!" };

logic_error c = "crap!";
}

Here the crappy declaration of `c` fails to compile, because both
eligible constructors are `explicit`.

Ike Naar

unread,
Sep 13, 2016, 1:17:59 PM9/13/16
to
On 2016-09-12, Alf P. Steinbach <alf.p.stein...@gmail.com> wrote:
> On 12.09.2016 03:01, Stefan Ram wrote:
>> I once had the idea of using direct-list-initialization
>> whenever possible since it is using the "uniform initialization
>> syntax", so it would be easy and tidy to use the same
>> notation whenever possible.
>
> Not quite the same. E.g.

std::string s{5, 'x'};

does not mean the same as

std::string s(5, 'x');

What's the differenece?

Alf P. Steinbach

unread,
Sep 13, 2016, 1:35:33 PM9/13/16
to
The first gives a string with the two values char(5) and char('x').

The second gives a string with five char('x') values.

This is also a problem with `std::vector`.

• • •

To work around that problem in new code we need some way to have named
constructors, preferably a way that's better than the Named Constructor
Idiom (which is just a factory function).

And just the other day I had an idea for that, namely a namespace
convention where types in `cs` are Constructor Selectors.

In order to support multiple definitions of the same name I envisioned a
simple template support and convention, like this:

namespace cs {
template< class Type >
struct Constructor_selector {};
}

so that one can define e.g.

namespace cs {
using Sequence = Constructor_selector<struct Sequence_>;
using Times = Constructor_selector<struct Times_>;
}

and write e.g.

String{ cs::Sequence(), 5, 'x' }
+
String{ 'x', 5, cs::Times() }

• • •

I think it would be better, it would be good, if there was something
like ADL that would look up a type or other name that's used in a
constructor invocation, in that constructor's class. Then one could
define such types or value names in the class, and avoid the less
readable qualifications. But alas, I think there's no chance of that!

Victor Bazarov

unread,
Sep 13, 2016, 2:18:50 PM9/13/16
to
On 9/13/2016 2:00 PM, Stefan Ram wrote:
> [...]
> int main ()
> { { string s( 2, 65 ); ::std::cout << s << '\n'; }
> { string s{ 2, 65 }; ::std::cout << s << '\n'; }
> { stringfromlist s( 2, 65 ); ::std::cout << s << '\n'; }
> { stringfromlist s{ 2, 65 }; ::std::cout << s << '\n'; }}
>
> Above, »string ... 2, 65« always means »two 'A'«, and
> »stringfromlist ... 2, 65« always means »(char)2« and »'A'«.
>

No, not *always*. If you'd have written ...2, 'A'..., then _always_.
Not on all systems ASCII encoding it used, see EBCDIC.

V
--
I do not respond to top-posted replies, please don't ask

Alf P. Steinbach

unread,
Sep 14, 2016, 6:20:48 AM9/14/16
to
On 13.09.2016 20:00, Stefan Ram wrote:
> "Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
>> On 13.09.2016 19:17, Ike Naar wrote:
>>>> Not quite the same. E.g.
>>> std::string s{5, 'x'};
>>> does not mean the same as
>>> std::string s(5, 'x');
>>> What's the differenece?
>> The first gives a string with the two values char(5) and char('x').
>> The second gives a string with five char('x') values.
>> This is also a problem with `std::vector`.
>
> Well, "problem"?
>
> It sounded like this to me:
>
> ||What's the difference between "5+2" and "5-2"?
> |
> |The first one gives 7 and the second one 3.
> |
> |This is also a problem with "*" and "/".

In most cases the two constructor call notations give the same result.

It's usually unexpected when they don't mean the same, because it isn't
clear from the calling code, and it depends on the concrete classes.

That's a problem.

And in the standard library it's mainly a problem with
`std::basic_string` and `std::vector`.

The fix direction I proposed addressed the lack of clarity in the
calling code.


> I sometimes used something like this:
>
> #include <iostream>
> #include <initializer_list>
> #include <ostream>
> #include <string>
>
> using namespace ::std::literals;
>
> struct string : public ::std::string
> { //using ::std::string::string;
> string( size_type const n, char const c ):
> ::std::string( n, c ){}; };
>
> struct stringfromlist : public ::std::string
> { stringfromlist( char const n, char const c ):
> ::std::string{ n, c }{};
> stringfromlist( ::std::initializer_list< char > const list ):
> ::std::string( list ){}; };
>
> void p( ::std::string const s ) { ::std::cout << s << '\n'; }
> int main ()
> { { string s( 2, 65 ); ::std::cout << s << '\n'; }
> { string s{ 2, 65 }; ::std::cout << s << '\n'; }
> { stringfromlist s( 2, 65 ); ::std::cout << s << '\n'; }
> { stringfromlist s{ 2, 65 }; ::std::cout << s << '\n'; }}
>
> Above, »string ... 2, 65« always means »two 'A'«, and
> »stringfromlist ... 2, 65« always means »(char)2« and »'A'«.

To my eyes all these prefixes are visual noise that make the code pretty
unreadable, but I have talked with Norwegian programmers who claim that
on the contrary, when they get used to it the prefixes increase
readability for them. I can't fathom how. But.

Ditto for the indentation convention, I can't see how you can get used
to that at all. Do tools such as AStyle support that?

Anyway, one technical problem with this approach is that the derived
classes can affect overload resolution so that e.g. operators are not
found. I was surprised to find that unqualified `swap` worked with
arguments of the two different derived classes. Someone will no doubt
find an explanation for that apparent weirdness. It's both about the ADL
and about the template argument deduction. But as an example that works,
in the sense that it fails to compile, consider:

template< class Type >
void foo( Type&, Type& ) {}

int main ()
{ {string a( 1, 'A' ); stringfromlist b( 2, 'A' ); foo( a, b ); }}

Bo Persson

unread,
Sep 14, 2016, 11:21:13 AM9/14/16
to
On 2016-09-14 14:06, Stefan Ram wrote:
> "Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
>> To my eyes all these prefixes are visual noise that make the code pretty
>> unreadable, but I have talked with Norwegian programmers who claim that
>> on the contrary, when they get used to it the prefixes increase
>> readability for them. I can't fathom how. But.
>
> The prefixes explain where the names come from.
>
> For example »if( ::std::example() > ::sky::example() )«
> makes it clear that the first name comes from the
> standard library and the second one from a custom
> library.
>

For the rest of us the noise is that if std::example isn't the same as
::std::example, the code base is so fucked up that you should just
discard it and start over.

Anyone adding a sky::std::string deserves a public flogging, so trying
to defend against that is a wasted effort. And makes the code unreadable.


Bo Persson




Ian Collins

unread,
Sep 14, 2016, 4:08:52 PM9/14/16
to
It's a bit like the Swiss defending against a seaborne invasion...

--
Ian

Reinhardt Behm

unread,
Sep 14, 2016, 8:16:46 PM9/14/16
to
There is Lake Constance. ;-)

--
Reinhardt

woodb...@gmail.com

unread,
Sep 14, 2016, 10:59:18 PM9/14/16
to
On Wednesday, September 14, 2016 at 10:21:13 AM UTC-5, Bo Persson wrote:

Bo, please don't swear here.

Brian
Ebenezer Enterprises
http://webEbenezer.net

woodb...@gmail.com

unread,
Sep 14, 2016, 11:14:55 PM9/14/16
to
It seems to me that every country needs to defend itself from
missiles launched from ships.

I also use that :: prefix. An ounce of prevention is worth
more than a pound of cure.

Brian
Ebenezer Enterprises - In G-d we trust.
http://webEbenezer.net

red floyd

unread,
Sep 15, 2016, 1:17:50 AM9/15/16
to
On 9/14/2016 7:58 PM, woodb...@gmail.com wrote:
> On Wednesday, September 14, 2016 at 10:21:13 AM UTC-5, Bo Persson wrote:
>
> Bo, please don't swear here.
>
Fuck off about that, will you?


David Brown

unread,
Sep 15, 2016, 4:44:43 AM9/15/16
to
On 15/09/16 04:58, woodb...@gmail.com wrote:
> On Wednesday, September 14, 2016 at 10:21:13 AM UTC-5, Bo Persson wrote:
>
> Bo, please don't swear here.
>

You are quite happy with threats of public flogging, but a little
colourful language for emphasis gets your knickers in a twist? You
really have got your priorities messed up.

(Not that I think there is anything wrong with Bo's recommended
punishment here - most people don't take such suggestions literally.)


David Brown

unread,
Sep 15, 2016, 4:46:52 AM9/15/16
to
Do you also walk around wearing a life jacket, just in case you need it?

When the "prevention" gets in the way, and offers no more than minimal
protection against something that is highly unlikely to happen, then it
is a /bad/ idea.



Scott Lurndal

unread,
Sep 15, 2016, 8:40:18 AM9/15/16
to
woodb...@gmail.com writes:
>On Wednesday, September 14, 2016 at 3:08:52 PM UTC-5, Ian Collins wrote:

>> It's a bit like the Swiss defending against a seaborne invasion...
>>=20
>
>It seems to me that every country needs to defend itself from
>missiles launched from ships.

It seems to me that you don't understand the meaning of the word _invasion_.

woodb...@gmail.com

unread,
Sep 15, 2016, 11:46:11 AM9/15/16
to
It could happen due to ignorance, maliciousness or by accident,
so I disagree that it's highly unlikely.

If the use of a :: prefix is considered odd by some, keep
in mind the people of G-d are called to be a peculiar people:

"But you are a chosen people, a royal priesthood, an holy nation,
a peculiar people; that ye should show forth the praises of Him
who hath called you out of darkness into His marvelous light"
1st Peter 2:9

woodb...@gmail.com

unread,
Sep 15, 2016, 11:51:18 AM9/15/16
to
I don't want my country invaded by people or missiles.

woodb...@gmail.com

unread,
Sep 15, 2016, 12:06:52 PM9/15/16
to
http://www.webster-dictionary.org/definition/peculiar

Pe`cul´iar
a. 1. One's own; belonging solely or especially to an individual;
not possessed by others; of private, personal, or characteristic
possession and use; not owned in common or in participation.

And purify unto himself a peculiar people.
- Titus 2: 14.

David Brown

unread,
Sep 15, 2016, 12:33:32 PM9/15/16
to
Programming is not religion. Your religion and your beliefs are
entirely up to /you/ - no one else is interested or wants to know.

Code that you show other people, on the other hand, is not just for you
- that is the whole point. So there is no place for "peculiarities"
like this in such code. If you are going to show code to other people,
make an effort to make it as clear and sensible as you can. When almost
everyone else tells you a :: prefix to std:: is ugly, unnecessary and
distracting, then you should listen to them.

Tim Rentsch

unread,
Sep 15, 2016, 1:10:38 PM9/15/16
to
Bo Persson <b...@gmb.dk> writes:

> For the rest of us the noise is that if std::example isn't the
> same as ::std::example, the code base is so [expletive] up that
> you should just discard it and start over.
>
> Anyone adding a sky::std::string deserves a public flogging, [...]

ITYM ::sky::std::string ;)

Vir Campestris

unread,
Sep 15, 2016, 4:27:06 PM9/15/16
to
On 14/09/2016 13:06, Stefan Ram wrote:
> while( fgets( eingabe, sizeof eingabe, stdin ))
> if( sscanf( eingabe, "%d", &wert )!= 1 )
> fprintf( stderr, "Please enter a number!\n" );
> else
> summe += wert;

I like my braces on separate lines. That way when I add something into
the code you can clearly see what I really did.

while( fgets( eingabe, sizeof eingabe, stdin ))
if( sscanf( eingabe, "%d", &wert )!= 1 )
+ {
fprintf( stderr, "Please enter a number!\n" );
+ ++errcount;
+ }
else
summe += wert;

In your style that would be

while( fgets( eingabe, sizeof eingabe, stdin ))
if( sscanf( eingabe, "%d", &wert )!= 1 ) {
- { fprintf( stderr, "Please enter a number!\n" );
+ { fprintf( stderr, "Please enter a number!\n" );
+ ++errcount; }
else
summe += wert;

and git blame would blame me for using fprintf in a C++ programme.

(I don't like Git - but we use Android, so I'm stuck with it. And some
of the time I'm stuck with Linus' coding standards too :( )

Andy

David Brown

unread,
Sep 15, 2016, 5:20:20 PM9/15/16
to
On 15/09/16 22:26, Vir Campestris wrote:
> On 14/09/2016 13:06, Stefan Ram wrote:
>> while( fgets( eingabe, sizeof eingabe, stdin ))
>> if( sscanf( eingabe, "%d", &wert )!= 1 )
>> fprintf( stderr, "Please enter a number!\n" );
>> else
>> summe += wert;
>
> I like my braces on separate lines. That way when I add something into
> the code you can clearly see what I really did.
>
> while( fgets( eingabe, sizeof eingabe, stdin ))
> if( sscanf( eingabe, "%d", &wert )!= 1 )
> + {
> fprintf( stderr, "Please enter a number!\n" );
> + ++errcount;
> + }
> else
> summe += wert;
>
> In your style that would be
>
> while( fgets( eingabe, sizeof eingabe, stdin ))
> if( sscanf( eingabe, "%d", &wert )!= 1 ) {
> - { fprintf( stderr, "Please enter a number!\n" );

I think you've got an extra bracket in there.

> + { fprintf( stderr, "Please enter a number!\n" );
> + ++errcount; }
> else
> summe += wert;
>
> and git blame would blame me for using fprintf in a C++ programme.
>
> (I don't like Git - but we use Android, so I'm stuck with it. And some
> of the time I'm stuck with Linus' coding standards too :( )
>

I prefer the "One true brace style", as well as always including braces
in conditionals. So I would write:


while (fgets(eingabe, sizeof eingabe, stdin)) {
if (sscanf(eingabe, "%d", &wert) != 1) {
fprintf(stderr, "Please enter a number!\n");
} else {
summe += wert;
}
}

And after the change, it would be

while (fgets(eingabe, sizeof eingabe, stdin)) {
if (sscanf(eingabe, "%d", &wert) != 1) {
fprintf(stderr, "Please enter a number!\n");
+ ++errcount;
} else {
summe += wert;
}
}

Then git would only blame me for the change I actually made.

woodb...@gmail.com

unread,
Sep 15, 2016, 8:12:22 PM9/15/16
to
Anyone is welcome to read the part of the code that's open source,
but the primary audience is the royal priesthood. The :: prefix
can be considered as part of the signature of the royal priesthood.

"But you are a chosen generation, a royal priesthood, an holy nation,
a peculiar people; that you should show forth the praises of Him who
hath called you out of darkness into His marvelous light."

woodb...@gmail.com

unread,
Sep 15, 2016, 8:29:05 PM9/15/16
to
"We few, we happy few, we band of brothers." Shakespeare

Öö Tiib

unread,
Sep 16, 2016, 2:45:02 AM9/16/16
to
So you declare yourself and Stefan Ram to be "royal priesthood" thanks
to redundant colons? :D

woodb...@gmail.com

unread,
Sep 16, 2016, 11:01:13 AM9/16/16
to
I claim to be a part of it. I'm not sure about Stefan. I hope
he is, but I can't be sure just by this.

Öö Tiib

unread,
Sep 16, 2016, 2:10:07 PM9/16/16
to
Hopefully the colons are good reason to humble oneself.

Vir Campestris

unread,
Sep 16, 2016, 4:17:34 PM9/16/16
to
On 16/09/2016 07:44, Öö Tiib wrote:
> So you declare yourself and Stefan Ram to be "royal priesthood" thanks
> to redundant colons? :D

At least they don't wear them on their heads :P

(yes, I know umlauts aren't really redundant)

Andy

Victor Bazarov

unread,
Sep 16, 2016, 4:25:30 PM9/16/16
to
On 9/16/2016 4:17 PM, Vir Campestris wrote:
> On 16/09/2016 07:44, Öö Tiib wrote:
>> So you declare yourself and Stefan Ram to be "royal priesthood" thanks
>> to redundant colons? :D
>
> At least they don't wear them on their heads :P

No, they just wear their heads inside their colons...

woodb...@gmail.com

unread,
Sep 16, 2016, 8:49:20 PM9/16/16
to
Baseless insults...


One thing I'm proud of is my business model -- making the
on line service free. I wish I could say it was my idea,
but a friend suggested it to me and at first I didn't like
the idea, but after a few weeks it started to make sense to me.
Many companies have 30 days of free trial now, but not that
many have completely free services. My friend gave me a good
idea and I have run with it.




Stefa...@f10.n2.z21

unread,
Sep 18, 2016, 7:33:57 AM9/18/16
to
e90a51a2
Ike Naar <i...@iceland.freeshell.org> writes:
>std::string s{5, 'x'};
>does not mean the same as
>std::string s(5, 'x');
>What's the differenece?

The first one is called »direct-list-initialization«
and the second one »direct-initialization«.

(Direct-)list-intialization prefers initializer-list
constructors (8.6.4) by »13.3.1.7 Initialization by
list-initialization [over.match.list]«, unless the
initializer list has no elements and T has a default
constructor.

0 new messages