- All-caps (was Re: enum class, auto) - 17 Updates
- private static member variables - 7 Updates
- private static member variables - 1 Update
"Öö 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:
Post a Comment