Sunday, January 24, 2016

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

"Öö Tiib" <ootiib@hot.ee>: Jan 23 04:28PM -0800

On Saturday, 23 January 2016 17:17:14 UTC+2, Jorgen Grahn wrote:
 
> People interpret the all-caps thing differently. To you it says
> HERE_IS_MACRO; for others (like me) it says HERE_IS_A_CONSTANT. That
> split probably happened (without anyone noticing) in C in the 1980s.
 
The constants are actually safest thing in programming. Constants are
immutable and lack life-time so thread-safe, exception-safe and
whatever-else-safe. So being loud about those feels inappropriate.
That would be still only matter of taste if it was the only reason.
 
 
> I concede that your view won in some sense ... but personally I still
> haven't made the switch, and I suspect there are a lot of people like
> me. One of the many obstacles in our line of work ...
 
Seems so that mine side has collected more votes over time, sorry.
 
First time I took a rule to coding standard that all macros must be
capitalized and no non-macros should be capitalized was somewhere 1998
when <windows.h> screwed up the 'std::numeric_limits<T>::max()' with its
'min' and 'max' macros in one code-base. It was pain because some other
Microsoft header used was using those macros. Therefore I felt that
making unique difference in naming of macros is important in practice and
it is not only matter of taste.
"Öö Tiib" <ootiib@hot.ee>: Jan 23 04:36PM -0800

On Sunday, 24 January 2016 02:29:00 UTC+2, Öö Tiib wrote:
 
> First time I took a rule to coding standard that all macros must be
> capitalized and no non-macros should be capitalized ...
 
Perhaps the correct English term is "all caps" not "capitalized"? Does
latter mean only first letter made capital letter in English?
"Öö Tiib" <ootiib@hot.ee>: Jan 23 05:34PM -0800

On Saturday, 23 January 2016 18:55:54 UTC+2, David Brown wrote:
 
> It is no different from using any feature in any language - when there
> is more than one way to achieve the result, use the "best" method
> available for whatever criteria of "best" you think is most appropriate.
 
I trust we agree. I mean "to avoid" not in sense that to avoid like dragon
or plague but like usually poorer choice from the alternatives if there
are any. Sometimes there are no alternatives like when some name of
variable or enumerator needs to be stringized and so on.
 
 
> But the solution is not to give macros names in all-caps to show we are
> using a risky feature - the solution is not to write or use bad macros,
> thus avoiding using the feature in a risky manner!
 
The issue with naming is not because of actually defective or dangerous
implementations of macros but because there is limited supply of
meaningful short names and so it is easier when macros have unique
naming scheme that no other names use.
David Brown <david.brown@hesbynett.no>: Jan 24 12:28PM +0100

On 23/01/16 18:51, Alf P. Steinbach wrote:
> `errno` (in C++ the latter is guaranteed to be a macro, e.g. C++11
> §19.4/1). But as the source code size increases, so does the risk of
> unintended substitutions, and modern code gets large fast.
 
Why should there be any "inadvertent text substitution" ? Use macros
where appropriate, and in a way that is appropriate - don't use them
when they are not appropriate, and don't define them badly.
 
Using all-caps for macros is just pandering to bad programmers and bad
code. We should aim to weed out such bad code, not make it stand out.
David Brown <david.brown@hesbynett.no>: Jan 24 12:35PM +0100

On 23/01/16 19:23, Mr Flibble wrote:
>> available for whatever criteria of "best" you think is most appropriate.
 
> "Macros should be avoided" is good *general* advice given their
> associated problems sausages.
 
The appropriate "good general advice" here is "use the most suitable
language feature for the job". Often, that is /not/ macros. And with
each generation of C++, the number of cases where macros are the best
choice has decreased. So certainly macro usage should be rare - but
/not/ because they are macros, merely because templates, constant
expressions, strong enumerations, inline functions, etc., are usually a
better choice.
Paavo Helde <myfirstname@osa.pri.ee>: Jan 24 01:42PM +0200

On 24.01.2016 2:36, 嘱 Tiib wrote:
>> capitalized and no non-macros should be capitalized ...
 
> Perhaps the correct English term is "all caps" not "capitalized"? Does
> latter mean only first letter made capital letter in English?
 
Interestingly enough, online dictionaries define "capitalize" as "write
in capital letters or with an initial capital letter", but "capitalise"
as "write in capital letters" only. See e.g.
http://www.memidex.com/capitalise where both definitions appear in the
same page. I have no idea if there is indeed a difference in the meaning
or not.
David Brown <david.brown@hesbynett.no>: Jan 24 12:57PM +0100

On 23/01/16 22:08, Chris Vine wrote:
> unnamespaceable (is that a word?), so they merit attention being given
> to them by using capitals, and they ought also to be prefixed as a
> substitute for a namespace.
 
No, they merit being given names that don't conflict with other names.
That is all.
 
Making macros, and only macros, all-caps is one way to avoid conflicts.
But it is neither necessary nor sufficient. It does nothing to stop
collisions between macro names, nor do you need to use all-caps to avoid
collisions.
 
This is no more and no less than the same namespace collision issues
that have always existed. For non-macro symbols, encapsulation in
classes and then namespaces have reduced the problem - or rather, pushed
it to a larger scale, allowing people to build bigger and bigger
programs while keeping control of their namespaces. Macros have not
benefited from this namespace scaling - this is a clear disadvantage.
But that does not mean that making them "shout" is a good answer.
 
> One example is from Qt. Their 'emit', 'signal' and 'slot' keywords are
> macros, and they are an abomination. They break boost, for example.
 
Qt is quite invasive - it is, in some ways, an extension to C++. If you
treat emit, signal and slot as keywords, then you have no problem.
Obviously that is going to be a problem for code that uses the same
identifiers for different purposes.
 
David Brown <david.brown@hesbynett.no>: Jan 24 01:06PM +0100

On 24/01/16 02:34, Öö Tiib wrote:
> or plague but like usually poorer choice from the alternatives if there
> are any. Sometimes there are no alternatives like when some name of
> variable or enumerator needs to be stringized and so on.
 
Yes, I think we agree there. My point is that macros are not evil.
Sometimes they are very useful, but often there are better ways to
handle the problem at hand.
 
> implementations of macros but because there is limited supply of
> meaningful short names and so it is easier when macros have unique
> naming scheme that no other names use.
 
That makes some sense - except that all-caps is a particularly ugly
naming scheme because it stands out so much. I also think it is wrong
to use a naming scheme for macros, when they are there to duplicate or
replace other code.
 
For example, you might be perfectly happy with a global constant:
 
static const int biggestNumber = 42;
 
If you need "biggestNumber" to be a macro - perhaps it depends on a
command-line parameter macro - why not write:
 
#define biggestNumber 42
 
You want to be able to use the macro version of "biggestNumber" in the
same way, and the same contexts, as the static const version. It
doesn't make any sense to me that you should rename it to BIGGEST_NUMBER.
Paavo Helde <myfirstname@osa.pri.ee>: Jan 24 02:54PM +0200

On 24.01.2016 14:06, David Brown wrote:
> replace other code.
 
> For example, you might be perfectly happy with a global constant:
 
> static const int biggestNumber = 42;
 
'static' is redundant here, namespace-scope 'const' already implies
internal linking in C++.
 
And no, I would not be happy with this constant if it is not placed
inside a specific namespace.
 
 
> If you need "biggestNumber" to be a macro - perhaps it depends on a
> command-line parameter macro - why not write:
 
> #define biggestNumber 42
 
This is much worse as now the definition is not contained/confined in
any namespace.
 
There is no need to use macros for constants in C++, whether in all-caps
or not.
 
> You want to be able to use the macro version of "biggestNumber" in the
> same way, and the same contexts, as the static const version.
 
But I can't. I cannot use it in another namespace which defines
biggestNumber.
 
 
> It
> doesn't make any sense to me that you should rename it to BIGGEST_NUMBER.
 
No, you should not rename it to BIGGEST_NUMBER, but to
SPECIFICPRODUCTNAME_BIGGEST_NUMBER. Cf. BOOST_STATIC_ASSERT,
BOOST_LIB_TOOLSET etc. This is all about avoiding the conflicts. And the
convention to use special spelling for macros also helps to reduce
conflicts, just because the rest of the code does not use them. In this
sense using all-caps for enum values is an anti-pattern as it increases
the chance of conflicts.
 
Cheers
Paavo
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jan 24 02:06PM +0100

On 1/24/2016 12:28 PM, David Brown wrote:
>> §19.4/1). But as the source code size increases, so does the risk of
>> unintended substitutions, and modern code gets large fast.
 
> Why should there be any "inadvertent text substitution" ?
 
Sorry, I fail to understand that question. It /sounds/ like a
rhetorical question meant to indicate that you know of a way to avoid
the problem, and that you're next going to describe that way.
 
 
> Use macros
> where appropriate, and in a way that is appropriate - don't use them
> when they are not appropriate, and don't define them badly.
 
But this is not a description of a way to avoid the problem.
 
 
> Using all-caps for macros is just pandering to bad programmers and bad
> code. We should aim to weed out such bad code, not make it stand out.
 
I.e., the Boost programmers, including e.g. Dave Abrahams, are in your
opinion "bad programmers", producing "bad code". Hm. I think this
argument, which involves some /name calling/, is very unconvincing.
 
• • •
 
There is, however, an alternative for those who don't want to use the
all uppercase convention for macros. Namely, Herb Sutter's advice [1]"If
you have to write a macro, try to give it an unusual and hard-to-spell
name that will be less likely to tromp on other names.".
 
The all uppercase convention serves that uniqueness purpose in a simple
way, usually combined with some short namespace-like prefix.
 
When you don't use the all uppercase macro name convention you have to
compensate with e.g. less collision-likely longer prefixes or suffixes,
which approach reduces readability, but is a technical possibility.
 
 
Cheers & hth.,
 
- Alf
 
Notes:
[1] <url: http://www.gotw.ca/gotw/077.htm>
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jan 24 02:13PM +0100

On 1/24/2016 1:06 PM, David Brown wrote:
 
> You want to be able to use the macro version of "biggestNumber" in the
> same way, and the same contexts, as the static const version. It
> doesn't make any sense to me that you should rename it to BIGGEST_NUMBER.
 
Defined macro names are few, defined ordinary names are legio.
 
So there is much higher probability that the name `biggestNumber` is in
use in some other part code, than that the name `BIGGEST_NUMBER` or, as
would be natural, `SOMEPREFIX_BIGGEST_NUMBER`, is in use or will later
be in use in some other part code, possibly in 3rd party library code
that you don't control.
 
This is all about improving the odds, not about any absolute certainty.
 
 
Cheers & hth.,
 
- Alf
Jerry Stuckle <jstucklex@attglobal.net>: Jan 24 11:20AM -0500

On 1/24/2016 6:28 AM, David Brown wrote:
> when they are not appropriate, and don't define them badly.
 
> Using all-caps for macros is just pandering to bad programmers and bad
> code. We should aim to weed out such bad code, not make it stand out.
 
I don't understand this statement. C is case sensitive - take advantage
of that fact. Using all upper case for macro names and #defined
constants clarifies what they are and means you won't have "inadvertent
text substitution". It also makes the code easier to maintain because
one doesn't have to look through every included file (and every file
THOSE include) to see if there might be a clash with a new variable or
function you have to define.
 
I would submit that NOT using all of the features of C (including case
sensitivity) is "just pandering to bad programmers and bad code."
 
You may not like it - but it's a long-established practice in both C and
C++, and for very good reasons.
 
--
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Jan 24 04:24PM

On 24/01/2016 11:35, David Brown wrote:
> /not/ because they are macros, merely because templates, constant
> expressions, strong enumerations, inline functions, etc., are usually a
> better choice.
 
Again that simply means that "macros should be avoided" is good
*general* advice; I know of at least one safety critical C++ coding
standard that actually prohibits the use of macros sausages.
 
/Flibble
Jerry Stuckle <jstucklex@attglobal.net>: Jan 24 11:24AM -0500

On 1/24/2016 7:06 AM, David Brown wrote:
 
> You want to be able to use the macro version of "biggestNumber" in the
> same way, and the same contexts, as the static const version. It
> doesn't make any sense to me that you should rename it to BIGGEST_NUMBER.
 
OK, now what happens when, while modifying the code, I want to add
something like:
 
int biggestNumber(int * array, int size) {
...
}
 
Which finds the largest number in an array? According to you, I need to
look through every included header and every header those include to
ensure I don't have a conflict.
 
--
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jan 24 06:20PM

On Sun, 24 Jan 2016 12:57:35 +0100
David Brown <david.brown@hesbynett.no> wrote:
[snip]
> conflicts. But it is neither necessary nor sufficient. It does
> nothing to stop collisions between macro names, nor do you need to
> use all-caps to avoid collisions.
 
You are missing the point. If you use all-caps for preprocessor names
and for nothing else then you isolate the name clash risk for macro
names to the preprocessor only. Then, as I previously said, you use a
prefix to avoid name clashes within what has become the macro namespace.
 
This is very well established practice, and for good reason. It is by
convention the way to do it, and arguing about it is just silly in my
opinion.
 
Chris
David Brown <david.brown@hesbynett.no>: Jan 24 08:26PM +0100

On 24/01/16 14:06, Alf P. Steinbach wrote:
>> where appropriate, and in a way that is appropriate - don't use them
>> when they are not appropriate, and don't define them badly.
 
> But this is not a description of a way to avoid the problem.
 
What problem? "Inadvertent text substitution" just means "I've made a
mistake in my coding that happens to involve a macro", as far as I can
see. It is not fundamentally different from any other kind of mistake.
 
Now, I am all in favour of programming habits that reduce the risk of
mistakes - and I am quite happy with "don't use macros unless they make
a significant benefit to the code" as such a habit.
 
What I /don't/ see is the idea that macros are so specially bad that it
is appropriate to disrupt the flow of the code and make them stand out
above all other identifiers.
 
 
> I.e., the Boost programmers, including e.g. Dave Abrahams, are in your
> opinion "bad programmers", producing "bad code". Hm. I think this
> argument, which involves some /name calling/, is very unconvincing.
 
If these folks /need/ to use all-caps names for macros, then they are
doing something wrong.
 
Namespace collisions happen. It's almost inevitable. Macros certainly
don't help the matter because they don't follow scope rules, but they
are not the only type of collision possible.
 
The way to avoid problems with namespace collisions (through macros or
anything else) is, I think, threefold. First, make sure that your
library/header suppliers know what they are doing, and don't use common
names for anything in a wider scope than necessary. This applies to
macros, but it also applies to global functions, types, enumerators,
etc., just as much. Second, make sure that /you/ know what you are
doing, and understand what symbols exist at the different scopes and
namespaces you are using. Third, use tools (such as a good editor or
IDE) that help you get things right.
 
> all uppercase convention for macros. Namely, Herb Sutter's advice [1]"If
> you have to write a macro, try to give it an unusual and hard-to-spell
> name that will be less likely to tromp on other names.".
 
That sounds like reasonable advice.
 
 
> The all uppercase convention serves that uniqueness purpose in a simple
> way, usually combined with some short namespace-like prefix.
 
I understand that. Naming conventions can be a useful thing, and
namespace-like prefixes are an age-old tool for this purpose.
 
My point is nothing more, and nothing less, than that an all-caps
convention is not necessary for macros, and that this convention
interferes with clear programming. I don't think macros as a class need
a naming convention. And I think that using all-caps encourages the
belief (not followed by everyone here) that macros are someone dangerous
and scary, and need to stand out so that they can be treated with
special care.
 
 
> When you don't use the all uppercase macro name convention you have to
> compensate with e.g. less collision-likely longer prefixes or suffixes,
> which approach reduces readability, but is a technical possibility.
 
It is all a balance, and will depend on the kind of code being written,
and the size of the project.
David Brown <david.brown@hesbynett.no>: Jan 24 08:30PM +0100

On 24/01/16 17:24, Mr Flibble wrote:
 
> Again that simply means that "macros should be avoided" is good
> *general* advice; I know of at least one safety critical C++ coding
> standard that actually prohibits the use of macros sausages.
 
Most C and C++ standards that I have seen - safety-critical or not -
discourage the use of macros. And I agree that where there are
alternatives, they are almost always a better idea. I would even list
"less need of macros" as one of the advantages of C++ over C. But there
are types of code problems which are best solved with macros - and if
they result in clearer and more reliable code, they are a good thing.
Paul <pepstein5@gmail.com>: Jan 24 05:13AM -0800

Why does the below compile? Hasn't the private member ex been accessed from outside the class?
 
Thanks,
 
Paul
 
class test
{
static int ex;
};
 
int test::ex = 1;
 
int main()
{
 
}
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jan 24 02:22PM +0100

On 1/24/2016 2:13 PM, Paul wrote:
 
> int main()
> {
 
> }
 
The declaration outside the class is a definition. Of a private member.
It would be rather impractical if you couldn't define private members
outside the class, so the language allows it.
 
By the way, the declaration is a definition /because/ it's outside the
class, not because of the `=` initialization.
 
Indeed, because `int` is an integral type, if it were `const` then you
could write
 
class test
{
static const int ex = 1;
};
 
const int test::ex;
 
 
and still the declaration in the class (now with initialization) would
be a pure declaration, and the declaration after the class a definition.
 
 
Cheers & hth.,
 
- Alf
Paavo Helde <myfirstname@osa.pri.ee>: Jan 24 03:26PM +0200

On 24.01.2016 15:13, Paul wrote:
> static int ex;
> };
 
> int test::ex = 1;
 
No, the prefix test:: shows the definition belongs into the class test
and in this sense this line is "inside the class".
 
This is the same as defining member functions outside of the class
definition itself.
 
hth
Paavo
Paavo Helde <myfirstname@osa.pri.ee>: Jan 24 03:56PM +0200

On 24.01.2016 15:48, Stefan Ram wrote:
 
> In C++, we even deem »operator +« and »operator >>« to be
> »part of the class ::pair::pair«, even though they're not
> even declared within the class specifier.
 
Who is "we"? And no, these are not part of the class (they cannot access
private members of the class, for example).
 
Maybe you wanted to say such operators may be considered as a part of
the informal *interface* of the class?
Paavo Helde <myfirstname@osa.pri.ee>: Jan 24 04:20PM +0200

On 24.01.2016 16:02, Stefan Ram wrote:
> (a) "mention" X, and
> (b) are "supplied with" X
> are logically part of X«
 
Note he uses term "logically", as an opposite to "actually".
Gareth Owen <gwowen@gmail.com>: Jan 24 03:48PM

>> (b) are "supplied with" X
>> are logically part of X«
 
> Note he uses term "logically", as an opposite to "actually".
 
Notice what Stefan originally said, with which you dissented:
 
In C++, we even deem »operator +« and »operator >>« to be
»part of the class ::pair::pair«, even though they're not
even declared within the class specifier.
 
It's clear that Stefan and Herb's view on this are the same.
"they are logically part of X" <=> "we deem them to be part of X"
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jan 24 06:43PM

On Sun, 24 Jan 2016 15:48:27 +0000
> even declared within the class specifier.
 
> It's clear that Stefan and Herb's view on this are the same.
> "they are logically part of X" <=> "we deem them to be part of X"
 
I think that is a false argument, but whether you are right or wrong,
the response by Stefan was (in classic Stefan style) of no relevance to
the question raised by the original poster.
 
There is no comparison to be made between private static data members,
and free standing functions which have a class type as their first
argument. The first are not part of the class interface, whereas the
second are part of the class interface in some people's view (including
mine).
 
Chris
ram@zedat.fu-berlin.de (Stefan Ram): Jan 24 01:48PM

>The declaration outside the class is a definition. Of a private member.
>It would be rather impractical if you couldn't define private members
>outside the class, so the language allows it.
 
In C++, we even deem »operator +« and »operator >>« to be
»part of the class ::pair::pair«, even though they're not
even declared within the class specifier.
 
#include <iostream>
#include <ostream>
 
namespace pair
{
class pair
{ double x, y;
public:
pair( double const x = 0, double const y = 0 ): x{ x }, y{ y } {}
pair & operator ++() { ++x; return *this; }
pair operator ++( int )
{ auto result = *this; ++*this; return result; }
pair & operator +=( const pair & o )
{ x += o.x; y += o.y; return *this; }
::std::ostream & print( ::std::ostream & stream ) const
{ return stream << '<' << x << ", " << y << '>'; }};
 
inline pair operator +( pair result, pair const & other )
{ result += other; return result; }
 
inline ::std::ostream& operator <<
( ::std::ostream & stream, pair const & object )
{ return object.print( stream ); }}
 
int main()
{ ::pair::pair const c;
::std::cout << c << '\n'; }
 
If someone deems »<<« to be a part of the class
»::pair::pair«, should he then also deem it to
be part of the class »::std::ostream«?
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: