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

using #define vs const int , in error codes

109 views
Skip to first unread message

JiiPee

unread,
Nov 11, 2015, 1:39:26 PM11/11/15
to
I sometimes see that error codes are coded like:

#define ERROR_IN_INPUT 1
#define TOO_LONG_INPUT 2
#define PARAMETER_ERROR 3

I was taught that const int is better than define, so why is it not:

const int ERROR_IN_INPUT = 1;
const int TOO_LONG_INPUT = 2;
const int PARAMETER_ERROR = 3;

?
is there some/any benefit for using define here? I thought that was
C-programming...

Alf P. Steinbach

unread,
Nov 11, 2015, 1:52:18 PM11/11/15
to
It may be that these id's are used in sources other than C or C++ source
code, and/or by tools other than C or C++ compilers.

For example, although it doesn't relate so well to error codes, the
Windows RC resource definition language depends on preprocessing via the
C preprocessor, which simplifes the task of connecting resource
definitions to C and C++ code. One can simply include a common suitably
restricted header in both an RC file and C and C++ souce code files.

And Windows API symbolic error code names are processed by the Message
Compiler, mc.exe. Essentially it produces a message resource that can be
embedded in a DLL, and accessed via the FormatMessage API function, e.g.
via Microsoft's errlook utility, or via PowerShell.

Of course the reason for the error codes you see could be anything really.

It could be sheer force of habit, perhaps strongly influenced by seeing
(but not understanding) this convention used for e.g. Windows error codes.


Cheers & hth.,

- Alf

JiiPee

unread,
Nov 11, 2015, 2:29:26 PM11/11/15
to
On 11/11/2015 18:51, Alf P. Steinbach wrote:
>
> It may be that these id's are used in sources other than C or C++
> source code, and/or by tools other than C or C++ compilers.
>

Ok, so its some compilation issue. But if there is currently no usage
other than using it in the same program then maybe could do them as
const int. If later on other programs do need them then they can easily
be chenged to #define s.

Richard

unread,
Nov 11, 2015, 4:31:41 PM11/11/15
to
[Please do not mail me a copy of your followup]

n...@notvalid.com spake the secret code
<hXL0y.125075$L65....@fx47.am4> thusly:

>I sometimes see that error codes are coded like:
>
>#define ERROR_IN_INPUT 1
>#define TOO_LONG_INPUT 2
>#define PARAMETER_ERROR 3
>
>I was taught that const int is better than define, so why is it not:
>
>const int ERROR_IN_INPUT = 1;
>const int TOO_LONG_INPUT = 2;
>const int PARAMETER_ERROR = 3;

Prefer constants (as you have done) or enums over #define for C++ code
bases.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

JiiPee

unread,
Nov 11, 2015, 4:39:01 PM11/11/15
to
On 11/11/2015 21:31, Richard wrote:
> [Please do not mail me a copy of your followup]
>
> n...@notvalid.com spake the secret code
> <hXL0y.125075$L65....@fx47.am4> thusly:
>
>> I sometimes see that error codes are coded like:
>>
>> #define ERROR_IN_INPUT 1
>> #define TOO_LONG_INPUT 2
>> #define PARAMETER_ERROR 3
>>
>> I was taught that const int is better than define, so why is it not:
>>
>> const int ERROR_IN_INPUT = 1;
>> const int TOO_LONG_INPUT = 2;
>> const int PARAMETER_ERROR = 3;
> Prefer constants (as you have done) or enums over #define for C++ code
> bases.

ye I do, but I just see that some people use defines...

Öö Tiib

unread,
Nov 11, 2015, 9:31:30 PM11/11/15
to
One benefit can be if those constants are used in '#if' conditions
of preprocessor (that is usually avoided in C++) or in other tools.

If the constants are used only in code then it is perhaps good idea to
avoid capitalizing them in screaming caps. Also if these are meant as
selection of values, (like your error codes) then enum is likely best.

Richard

unread,
Nov 12, 2015, 1:21:39 PM11/12/15
to
[Please do not mail me a copy of your followup]

n...@notvalid.com spake the secret code
<uzO0y.321008$qX.1...@fx45.am4> thusly:

>On 11/11/2015 21:31, Richard wrote:
>> [Please do not mail me a copy of your followup]
>> Prefer constants (as you have done) or enums over #define for C++ code
>> bases.
>
>ye I do, but I just see that some people use defines...

Yes. Ignore those people and do not emulate or copy them. They are C
programmers. You can do better with C++.

JiiPee

unread,
Nov 12, 2015, 4:05:06 PM11/12/15
to
On 12/11/2015 18:21, Richard wrote:
> [Please do not mail me a copy of your followup]
>
> n...@notvalid.com spake the secret code
> <uzO0y.321008$qX.1...@fx45.am4> thusly:
>
>> On 11/11/2015 21:31, Richard wrote:
>>> [Please do not mail me a copy of your followup]
>>> Prefer constants (as you have done) or enums over #define for C++ code
>>> bases.
>> ye I do, but I just see that some people use defines...
> Yes. Ignore those people and do not emulate or copy them. They are C
> programmers. You can do better with C++.

But this latest one, this was from a C++ code... so in C++ code they
used #defines to define contant integers... errors.

Vir Campestris

unread,
Nov 12, 2015, 4:14:57 PM11/12/15
to
On 12/11/2015 02:31, Öö Tiib wrote:
> If the constants are used only in code then it is perhaps good idea to
> avoid capitalizing them in screaming caps. Also if these are meant as
> selection of values, (like your error codes) then enum is likely best.

We always put #define-s in SCREAMING CAPS to remind people they
shouldn't be using them. Use an enum. Preferably n enum class.

Andy

Ian Collins

unread,
Nov 12, 2015, 5:11:36 PM11/12/15
to
That implies it is bad C++ code!

As Richard noted, this is a bad (in a C++ context) of C programmers
writing C++. There is no place for #define constants in C++ code.

--
Ian Collins

Ian Collins

unread,
Nov 12, 2015, 5:18:01 PM11/12/15
to
Should read "a bad habit".

--
Ian Collins

Richard

unread,
Nov 12, 2015, 5:49:01 PM11/12/15
to
[Please do not mail me a copy of your followup]

n...@notvalid.com spake the secret code
<Q971y.189951$wR.7...@fx43.am4> thusly:
The proof of what kind of programmer they are is in what kind of code
they wrote. Just slapping ".cpp" on the end of a file doesn't mean
you are writing C++ code, particularly if your code is full of C
programming habits.

If they are using #define for constants, they are C programmers IMO.

Sorry, but if you're going to argue against that position then I
don't consider you a C++ programmer.

Richard

unread,
Nov 12, 2015, 6:07:28 PM11/12/15
to
[Please do not mail me a copy of your followup]

(Richard) legaliz...@mail.xmission.com spake the secret code
<n2350g$c5k$1...@news.xmission.com> thusly:

>Sorry, but if you're going to argue against that position then I
>don't consider you a C++ programmer.

A slight clarification:

I mean you in a generic sense here, not specifically the author of the
post to which I was repsponding.

jacobnavia

unread,
Nov 13, 2015, 3:36:31 AM11/13/15
to
Le 12/11/2015 19:21, Richard a écrit :
> Yes. Ignore those people and do not emulate or copy them. They are C
> programmers. You can do better with C++.

I do not understand the need of C++ people to insult people that use
other languages.

Maybe that is a consequence of using c++ probably, an overly complex
language that takes so much place in your mind that good manners and
civilized behavior must be thrown out.

C programmers refuse the complexity and use #defines because they are
simple to use, they can be used in conditional compilation and they
belong to the C tradition of how things are done.

Contrary to popular beliefs among ignorant c++ users, C programmers have
enums available and they use it regularly instead of defines when
defines aren't appropiate.



jacobnavia

unread,
Nov 13, 2015, 3:38:50 AM11/13/15
to
Le 12/11/2015 22:04, JiiPee a écrit :
> But this latest one, this was from a C++ code... so in C++ code they
> used #defines to define contant integers... errors.

Obviously you are wrong. Please do not believe what your eyes see, do
not hear what your ears perceive and go on saying what politically
correct is in this newsgroup: c++ prpgrammers should not use defines.

Personally, I have never seen a serious C++ program without defines.

But of course, I am wrong. I will be always wrong because I program in C.

jacobnavia

unread,
Nov 13, 2015, 3:45:16 AM11/13/15
to
Le 12/11/2015 23:48, Richard a écrit :
> Sorry, but if you're going to argue against that position then I
> don't consider you a C++ programmer.


Oh my goodness. Are you implying that the poor chap is a C programmer?

What an insult!

Obviously I do not understand why c++ programmers need this arrogance.
Maybe it is caused by too reading too much templated code: they think in
templates and they use them in their everyday life with disastrous
consequences.

There is a for them a "C programmer" template, an obtuse and backwards
looking chap, unable to load all the c++ crap into their mind.

Then there is the c++ programmer template, the forward looking guru that
always finds an unnamed lambda an a corresponding templated virtual
class that can be added to make a simple application unreadable an
incomprehensible but for the intiated.

Look, there is NO NEED to insult other programmers. Just say why you
think some software feature is better adapted than another one and let
it be at that.

Argue, instead of displaying your arrogance Mister.

Öö Tiib

unread,
Nov 13, 2015, 4:31:49 AM11/13/15
to
On Friday, 13 November 2015 10:45:16 UTC+2, jacobnavia wrote:
> Le 12/11/2015 23:48, Richard a écrit :
> > Sorry, but if you're going to argue against that position then I
> > don't consider you a C++ programmer.
>
>
> Oh my goodness. Are you implying that the poor chap is a C programmer?
>
> What an insult!

:D Richard was clearly trolling and managed to waste our
time. Congrats Richard!

Microsoft's C compiler is slightly extended C89. Windows
is truly awful platform to run C on it. Microsoft's API
headers however are rather FULL OF #define constants.

> Look, there is NO NEED to insult other programmers.

Several times I have been in situation where C++ is not available:

1) No C++ compilers or libraries for target platform.
2) C++ does not run in browser (neither does C).
3) Most bright brain in team considers C++ a root of all evil.
4) "It must written be in C" is QUALIFIER requirement.

Öö Tiib

unread,
Nov 13, 2015, 4:41:28 AM11/13/15
to
On Friday, 13 November 2015 10:38:50 UTC+2, jacobnavia wrote:
>
> Personally, I have never seen a serious C++ program without defines.

I can confirm. Every C++ header in code-bases that I can reach has at
least one '#define' in it.

Shortest header from boost:
http://www.boost.org/doc/libs/1_55_0/boost/noncopyable.hpp

Like you see those '#define's do not define constants.

jacobnavia

unread,
Nov 13, 2015, 4:55:03 AM11/13/15
to
Yes, you can use enum, as I often do in C.

Note that I am not arguing against the use of enum for constants. What I
really do not like is the implicit pejorative use of the "C programmer"
here.

Richard

unread,
Nov 13, 2015, 12:07:18 PM11/13/15
to
[Please do not mail me a copy of your followup]

ja...@jacob.remcomp.fr spake the secret code
<n2479h$70g$1...@dont-email.me> thusly:

>Le 12/11/2015 19:21, Richard a écrit :
>> Yes. Ignore those people and do not emulate or copy them. They are C
>> programmers. You can do better with C++.
>
>I do not understand the need of C++ people to insult people that use
>other languages.

If you take that as an insult, that's your problem.

The fact is that C++ has better mechanisms for named constants than
preprocessor macros. C++ has had them for far longer than C has had
them. There isn't any excuse for perpetuating a weaker solution from
1973.

Modern C has enums and const integers as well, so even in C there is no
excuse for using the preprocessor for named constants. See the C11 ISO
standard; I consulted the April 12, 2011 committee draft.

Richard

unread,
Nov 13, 2015, 12:08:50 PM11/13/15
to
[Please do not mail me a copy of your followup]

ja...@jacob.remcomp.fr spake the secret code
<n247e8$70g$2...@dont-email.me> thusly:

>[...] c++ prpgrammers should not use defines.

Not for named integral constants.

There are still some valid uses of preprocessor macros and where
appropriate I use them.

Named integral constants is not one of those valid use cases.

You've created a nice straw-man argument that you've successfully
demolished. Congratulations! You've achieved absolutely nothing.

Richard

unread,
Nov 13, 2015, 12:09:20 PM11/13/15
to
[Please do not mail me a copy of your followup]

ja...@jacob.remcomp.fr spake the secret code
<n247q8$8nv$1...@dont-email.me> thusly:

>What an insult!

Waaaaaaaah.

becuz my feels.

Richard

unread,
Nov 13, 2015, 12:20:42 PM11/13/15
to
[Please do not mail me a copy of your followup]

ja...@jacob.remcomp.fr spake the secret code
<n24bst$m9f$1...@dont-email.me> thusly:

>Note that I am not arguing against the use of enum for constants. What I
>really do not like is the implicit pejorative use of the "C programmer"
>here.

If you're programming in C++, you should use C++ idioms, not C idioms.

You can program in C if you want to, I don't care.

Every time some Java programmer or C# programmer tells me how shitty
C++ code is, I ask them to show me the code.

THEY SHOW ME C CODE.

It will be full of buggy C-style string manipulation, control flow that
is a giant mess because of the obsession with avoiding exceptions in
the name of "efficiency" but instead causing the main path of the code
to be completely obscured by all the manual checking of error codes
and in-line error handling (exceptions are considered de jure in Java/C#),
and many other horrible habits.

Yes, it can be argued that some of these habits appear in programmers
working in any language. Bad control flow structure and long methods
or classes is certainly something I've seen often in C# and Java code.
However, there is no denying that there is something about the
profusion of examples of C code on the net and "C++" code on the net
that is really C-style programming masquerading as C++ programming
that gives some credence to the point made by C#/Java advocates.

Programming in C is demonstrably error-prone and verbose compared to
doing the same thing in C++. Yet there are certain aspects of C that are
desirable: its execution model maps directly to the actual hardware that
we use and it being the defacto binary API for most operating systems.
C++ is really different from other languages with it's philosophy of
"you don't pay for what you don't use". In Java or C# you don't
really have that option. There's a price for admission to the
language that C++ or C just doesn't have.

When you bring your C coding habits to C++, you bring with you all the
same problems that people have with C. No wonder people bitch that
C++ is a horrible language and they prefer Java/C# over it when every
time some "C++ programmer" creates some code on their team, they
create it with C style programming habits and all the weaknesses that
brings along with it.

I don't care if you want to program in C.

If you want to program in C++, embrace C++ and the mechanisms it has
that were created based on the experience of the shortcomings of C.
Using const and enum are just two tiny examples of where C++ took
advantage of the weakness of C based on actual usage of C and
improved upon it. These improvements are so universally acknowledged
that C itself incorporated those ideas back into the C standard from
C++.

The very fact that modern C includes enum and const is proving my
point and making you look silly by railing against me for objecting to
using #define for named integral constants.

Scott Lurndal

unread,
Nov 13, 2015, 12:27:12 PM11/13/15
to
legaliz...@mail.xmission.com (Richard) writes:
>[Please do not mail me a copy of your followup]
>
>ja...@jacob.remcomp.fr spake the secret code
><n2479h$70g$1...@dont-email.me> thusly:
>
>>Le 12/11/2015 19:21, Richard a écrit :
>>> Yes. Ignore those people and do not emulate or copy them. They are C
>>> programmers. You can do better with C++.
>>
>>I do not understand the need of C++ people to insult people that use
>>other languages.
>
>If you take that as an insult, that's your problem.
>
>The fact is that C++ has better mechanisms for named constants than
>preprocessor macros. C++ has had them for far longer than C has had
>them. There isn't any excuse for perpetuating a weaker solution from
>1973.
>
>Modern C has enums and const integers as well, so even in C there is no
>excuse for using the preprocessor for named constants. See the C11 ISO
>standard; I consulted the April 12, 2011 committee draft.

As has been pointed out to you repeatedly, not everyone can take
advantage of C11 and C++14. Nor do all real-word projects limit
themselves to a single language - it is not uncommon to mix C
and C++.

Use what is necessary for the project and don't be concerned with
"language purity".

JiiPee

unread,
Nov 13, 2015, 1:03:17 PM11/13/15
to
I guess people mean more like "C programmer doing C++ code with
C-style"...thus mixing styles. I guess what most here want is that C++
code is done using C++ styles. But if its a C-code, then its a different
matter, I guess all agree with that.

JiiPee

unread,
Nov 13, 2015, 1:17:54 PM11/13/15
to
On 13/11/2015 08:36, jacobnavia wrote:
> Le 12/11/2015 19:21, Richard a écrit :
>> Yes. Ignore those people and do not emulate or copy them. They are C
>> programmers. You can do better with C++.
>
> I do not understand the need of C++ people to insult people that use
> other languages.
>

I think, C language should normally only be used where there is no other
options, or is proven that its more efficient in something.
Like its true that a class takes more space than a POD. So if there is
very little memory, then maybe C is the only option and C++ programmer
should also use it.

But I do not see why some windows program would be done with C, as C++
makes it easier.

Richard

unread,
Nov 13, 2015, 1:48:59 PM11/13/15
to
[Please do not mail me a copy of your followup]

n...@notvalid.com spake the secret code
<9Pp1y.302134$%l3.2...@fx36.am4> thusly:

>On 13/11/2015 08:36, jacobnavia wrote:
>> Le 12/11/2015 19:21, Richard a écrit :
>>> Yes. Ignore those people and do not emulate or copy them. They are C
>>> programmers. You can do better with C++.
>>
>> I do not understand the need of C++ people to insult people that use
>> other languages.
>>
>
>I think, C language should normally only be used where there is no other
>options, or is proven that its more efficient in something.

As I've said elsewhere: I don't care if you program in C.

Please be honest with yourself and everyone else when you write
C-style code: don't call it C++ code. Using the excuse that C++ is
backwards compatible with C is just that -- an excuse for writing C
code.

As for the efficiency argument, it has been shown a bunch of times how
C++ can produce more efficient code than C. Boost.Spirit's example of
parsing integers faster than atoi is just one example. The reason C++
can achieve this is because C++ has a richer type system and more
information about types means the compiler can reason more explicitly
and expertly about how to treat those types. Inline functions and
generic algorithms, const, references, move semantics, and many other
features of modern C++ give the compiler many more opportunities for
optimization and optimizations that can be applied over larger
contexts.

In the worst case, C++ is no less efficient than C. In the best case,
C++ is more efficient than C.

Richard

unread,
Nov 13, 2015, 1:54:11 PM11/13/15
to
[Please do not mail me a copy of your followup]

sl...@pacbell.net spake the secret code
<A3p1y.141160$rR1.1...@fx19.iad> thusly:

>As has been pointed out to you repeatedly, not everyone can take
>advantage of C11 and C++14.

enum and const have been in C++ since the beginning. They do not
require C++14, C++11 or even C++03.

I did a little bit of googling to find out when enums were formally
added to the C language, but wikipedia and other articles didn't give
a chronology. I'm willing to bet that enums appeared in C before C11
and even before officially appearing in the standard were widely
supported in available implementations of C compilers such as gcc,
MSVC, etc.

>Nor do all real-word projects limit
>themselves to a single language - it is not uncommon to mix C
>and C++.

Then you don't have a C++ code base. You have a C code base with some
C++.

Of course you are held down by your weakest common denominator.

>Use what is necessary for the project and don't be concerned with
>"language purity".

Nice straw man. Nowhere have I ever advocated language purity. Only
you have said that in response to my posts advocating habits that are
driven by the pragmatic concerns of real-world programming. Avoid
error-prone facilities and use facilities that are created explicitly
to replace those that are error-prone with something that is less
error-prone.

Richard

unread,
Nov 13, 2015, 1:55:42 PM11/13/15
to
[Please do not mail me a copy of your followup]

sl...@pacbell.net spake the secret code
<A3p1y.141160$rR1.1...@fx19.iad> thusly:

>As has been pointed out to you repeatedly, not everyone can take
>advantage of C11 and C++14.

Also, you're moving the goal post here. Such restrictions were never
mentioned in the original post where the question was posed in a
general way.

Ian Collins

unread,
Nov 13, 2015, 3:10:11 PM11/13/15
to
Scott Lurndal wrote:
> legaliz...@mail.xmission.com (Richard) writes:
>> 1973.
>>
>> Modern C has enums and const integers as well, so even in C there is no
>> excuse for using the preprocessor for named constants. See the C11 ISO
>> standard; I consulted the April 12, 2011 committee draft.
>
> As has been pointed out to you repeatedly, not everyone can take
> advantage of C11 and C++14. Nor do all real-word projects limit
> themselves to a single language - it is not uncommon to mix C
> and C++.

I think you missed the point. In both C and C++ a better alternative to
#defines for error codes exists and has existed for decades: a simple enum.

--
Ian Collins

Ben Bacarisse

unread,
Nov 13, 2015, 4:32:49 PM11/13/15
to
legaliz...@mail.xmission.com (Richard) writes:
<snip>
> enum and const have been in C++ since the beginning. They do not
> require C++14, C++11 or even C++03.
>
> I did a little bit of googling to find out when enums were formally
> added to the C language, but wikipedia and other articles didn't give
> a chronology.

According to Dennis Ritchie:

"During 1973-1980, the language grew a bit: the type structure gained
unsigned, long, union, and enumeration types, and structures became
nearly first-class objects (lacking only a notation for literals)."[1]

enums are not in the first edition of "The C Programming Language"
(1978) but were in many compilers shortly after, and they are there in
the first ANSI standard of 1989.

[1] This is from "The Development of the C Language" which is probably
still available via Dennis Ritchie's Bell Labs/Lucent Technologies web
pages, but it's moved about a bit and I can't find a URL at the moment.

<snip>
--
Ben.

Robert Wessel

unread,
Nov 14, 2015, 2:53:46 AM11/14/15
to
I think that's all settled down to:

https://www.bell-labs.com/usr/dmr/www/

Vladislav Yaroslavlev

unread,
Nov 15, 2015, 3:23:22 PM11/15/15
to
On Wednesday, November 11, 2015 at 9:39:26 PM UTC+3, JiiPee wrote:
> I sometimes see that error codes are coded like:
>
> #define ERROR_IN_INPUT 1
> #define TOO_LONG_INPUT 2
> #define PARAMETER_ERROR 3
>
> I was taught that const int is better than define, so why is it not:
>
> const int ERROR_IN_INPUT = 1;
> const int TOO_LONG_INPUT = 2;
> const int PARAMETER_ERROR = 3;
>
> ?
> is there some/any benefit for using define here? I thought that was
> C-programming...

If you can use C++11, then better use `constexpr`:

constexpr int ERROR_IN_INPUT = 1;
constexpr int TOO_LONG_INPUT = 2;
constexpr int PARAMETER_ERROR = 3;

Vladislav Yaroslavlev

unread,
Nov 15, 2015, 3:30:10 PM11/15/15
to
Or much better variant:

===
using input_error_t = int;

enum class input_error : input_error_t
{
error_in_input = 1,
too_long_input = 2,
parameter_error = 3
};
===

Then use it:

===
// ... code ...

if (error == input_error::too_long_input)
{
// ... code ...
}

// ... code ...
===

This is IMHO the best variant.

jacobnavia

unread,
Nov 15, 2015, 4:49:06 PM11/15/15
to
Le 15/11/2015 21:29, Vladislav Yaroslavlev a écrit :
> enum class input_error : input_error_t
> {
> error_in_input = 1,
> too_long_input = 2,
> parameter_error = 3
> };
Mmmmmmmm

I fail to see why this is better than

enum error {input_error=1, too_long_input,parameter_error};

Can you maybe explain me that?

Thanks

Ian Collins

unread,
Nov 15, 2015, 4:55:47 PM11/15/15
to
If we leave aside the poor naming, the answer would be scope. Consider
the case where you want to reuse enumeration names. Here's a contrived
example:

enum OutputError { ToBig, ToSmall };
enum InputError { ToBig, ToSmall };

Obviously this will fail to compile, bu if we use an enum class:

enum class OutputError { ToBig, ToSmall };
enum class InputError { ToBig, ToSmall };

All is well.

--
Ian Collins

Vladislav Yaroslavlev

unread,
Nov 15, 2015, 5:10:15 PM11/15/15
to
First of all, it will not be implicitly converted to int. And it is great. Remember it's not C, it is C++.

And `enum class` is better than `enum` because you must specify enum class name before value, which is more readable.

See also here: Enums at C++ Core Guidelines: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#S-enum

jacobnavia

unread,
Nov 15, 2015, 5:14:33 PM11/15/15
to
Le 15/11/2015 22:55, Ian Collins a écrit :
> If we leave aside the poor naming, the answer would be scope. Consider
> the case where you want to reuse enumeration names.


Is that a good idea?


Besides, very often I use enums as bitfields:

enum foo{ property1=1,property2=2,property3=4,property4=8,property5=16};

Then I can say
if (val & property5)

That can't be done with scoped enums since there is no automatic
conversion to an integer. You would have to plaster your code with
static_cast<int>

The crux of the matter is the urge to compleixfy everything and not use
constructs that are simple to understand. I think that attitude leads to
bugs that are completely unnecessary and easy to avoid.

KEEP IT SIMPLE IAN!

jacobnavia

unread,
Nov 15, 2015, 5:19:37 PM11/15/15
to
Le 15/11/2015 23:10, Vladislav Yaroslavlev a écrit :
> First of all, it will not be implicitly converted to int. And it is great

Sure. But if you want to use the enums as a bitfield;

enum flags {
Archived=1,
Pending=2,
Received=4,
Sent=8,
Forwarded=16
};

I can now say

if (val &(Sent|Forwarded))

to test for some bit.

Using scoped enums I have to plaster all that with static_cast<int>

Remember, this is C++, not C. Everything must be a lot more complex than
it needs to!

:-)


Vladislav Yaroslavlev

unread,
Nov 15, 2015, 5:23:11 PM11/15/15
to
On Monday, November 16, 2015 at 1:14:33 AM UTC+3, jacobnavia wrote:
> Le 15/11/2015 22:55, Ian Collins a écrit :
> > If we leave aside the poor naming, the answer would be scope. Consider
> > the case where you want to reuse enumeration names.
> Is that a good idea?
>
>
> Besides, very often I use enums as bitfields:
>
> enum foo{ property1=1,property2=2,property3=4,property4=8,property5=16};
>
> Then I can say
> if (val & property5)

Why you need to do so? Please give a more full example.
We talk about particular case: constants for errors. Your example is from another area. Nobody removes old `enum`s from the language.

> That can't be done with scoped enums since there is no automatic
> conversion to an integer. You would have to plaster your code with
> static_cast<int>
>
> The crux of the matter is the urge to compleixfy everything and not use
> constructs that are simple to understand. I think that attitude leads to
> bugs that are completely unnecessary and easy to avoid.
>
> KEEP IT SIMPLE IAN!

You wrote in plain old C style, not C++.

jacobnavia

unread,
Nov 15, 2015, 5:27:42 PM11/15/15
to
Le 15/11/2015 23:23, Vladislav Yaroslavlev a écrit :
> Why you need to do so? Please give a more full example.

enum flags {
Archived=1,
Pending=2,
Received=4,
Sent=8,
Forwarded=16
};

I can now say

if (val &(Sent|Forwarded))

to test for several conditions with one VERY CHEAP operation.

That is the nice things about bit fields: compact (you can fit up to 32
properties in a single int in most systems), fast testing (a single
machine instruction) and clear.

True you can't reuse property names but that is so easy to solve...




Paavo Helde

unread,
Nov 15, 2015, 5:34:26 PM11/15/15
to
jacobnavia <ja...@jacob.remcomp.fr> wrote in news:n2avva$rbm$1@dont-
email.me:

> Le 15/11/2015 22:55, Ian Collins a écrit :
>> If we leave aside the poor naming, the answer would be scope. Consider
>> the case where you want to reuse enumeration names.
>
>
> Is that a good idea?
>
>
> Besides, very often I use enums as bitfields:
>
> enum foo{ property1=1,property2=2,property3=4,property4=8,property5=16};
>
> Then I can say
> if (val & property5)
>
> That can't be done with scoped enums since there is no automatic
> conversion to an integer. You would have to plaster your code with
> static_cast<int>

No, you define the needed operators like & and | for those enums with a
couple of one-liners. Sure, these lines consist mostly of casts, but the
rest of the code would be clean.

Cheers
Paavo

Ian Collins

unread,
Nov 15, 2015, 5:37:31 PM11/15/15
to
jacobnavia wrote:
> Le 15/11/2015 22:55, Ian Collins a écrit :
>> If we leave aside the poor naming, the answer would be scope. Consider
>> the case where you want to reuse enumeration names.
>
>
> Is that a good idea?
>
>
> Besides, very often I use enums as bitfields:
>
> enum foo{ property1=1,property2=2,property3=4,property4=8,property5=16};
>
> Then I can say
> if (val & property5)
>
> That can't be done with scoped enums since there is no automatic
> conversion to an integer. You would have to plaster your code with
> static_cast<int>

Or provide the appropriate operator. One of the reasons for adding enum
class was to prevent inadvertent conversion to int. Given bit fields
are unsigned types, enum class allows you to specify the underlying
type. So you could still write:

#include <stdint.h>

enum class Bit : uint8_t { Zero = 1, One = 2 };

bool operator | ( Bit b, uint8_t u )
{
return static_cast<uint8_t>(B) | u;
}

bool operator | ( uint8_t u, Bit b )
{
return u | static_cast<uint8_t>(b);
}

void f( uint8_t val )
{
Bit b;

if( val | Bit::Zero )
{
}
}

> The crux of the matter is the urge to compleixfy everything and not use
> constructs that are simple to understand. I think that attitude leads to
> bugs that are completely unnecessary and easy to avoid.

Inadvertent conversion to int can lead to unexpected bugs! The problem
is worse in C where assignment to an enum object from int is permitted.
Adding enum class just closes the gap the other way.

> KEEP IT SIMPLE IAN!

If you don't want to use an enum class, just carry on using an enum.
It's that simple!

--
Ian Collins

Vladislav Yaroslavlev

unread,
Nov 15, 2015, 5:38:21 PM11/15/15
to
The truth is that `enum` here is not semantically correct. You DO NOT enumerate anything. It's the hack: use one language feature for the purpose of another meaning.

You may choose for your flags is `constexpr` within its namespace:

namespace flags
{
constexpr auto Archived = 1,
constexpr auto Pending = 1 << 1,
constexpr auto Received = 1 << 2,
constexpr auto Sent = 1 << 3,
constexpr auto Forwarded = 1 << 4
}

No need for enum here, it is misunderstanding of enum.

But the best option for you is `std::bitset`.

jacobnavia

unread,
Nov 15, 2015, 5:43:34 PM11/15/15
to
Le 15/11/2015 23:38, Vladislav Yaroslavlev a écrit :
> The truth is that `enum` here is not semantically correct. You DO NOT enumerate anything

What?

I am enumerating the different states that a message can have: archived,
sent, whatever.

I do not see why you suppose that it is not an enumeration!


jacobnavia

unread,
Nov 15, 2015, 5:45:48 PM11/15/15
to
Le 15/11/2015 23:34, Paavo Helde a écrit :
> No, you define the needed operators like & and | for those enums with a
> couple of one-liners.

GOSH!

You want me to add lines of code to be able to do what plain enums give
me without any effort?

And I have to do that for each of these enums in my program?

KEEP IT SIMPLE ...

PLeeeeeeze.

:-)

jacobnavia

unread,
Nov 15, 2015, 5:48:32 PM11/15/15
to
Le 15/11/2015 23:37, Ian Collins a écrit :
> Or provide the appropriate operator. One of the reasons for adding enum
> class was to prevent inadvertent conversion to int. Given bit fields
> are unsigned types, enum class allows you to specify the underlying
> type. So you could still write:
>
> #include <stdint.h>
>
> enum class Bit : uint8_t { Zero = 1, One = 2 };
>
> bool operator | ( Bit b, uint8_t u )
> {
> return static_cast<uint8_t>(B) | u;
> }
>
> bool operator | ( uint8_t u, Bit b )
> {
> return u | static_cast<uint8_t>(b);
> }
>
> void f( uint8_t val )
> {
> Bit b;
>
> if( val | Bit::Zero )
> {
> }
> }


That's 13 lines of code to be done for each of those enums to do what
plain enum gives me for free.

Great Progress!

Look this is C++, I am no expert. I will just go on using enums...

Paavo Helde

unread,
Nov 15, 2015, 6:13:28 PM11/15/15
to
jacobnavia <ja...@jacob.remcomp.fr> wrote in news:n2b1q9$ul$2@dont-
email.me:

> Le 15/11/2015 23:34, Paavo Helde a écrit :
>> No, you define the needed operators like & and | for those enums with
a
>> couple of one-liners.
>
> GOSH!
>
> You want me to add lines of code to be able to do what plain enums give
> me without any effort?

Already the plain enums need casting when constructed from integers (like
the result of &), so in my code I have those operators also for many
plain enums.

>
> And I have to do that for each of these enums in my program?

No, only for those which need bitwise operations...

>
> KEEP IT SIMPLE ...

One can argue that having the enum and int types strictly separated makes
things simpler. There is a reason why we have types in the language.

I agree adding bitwise operators to an enum could be made simpler, e.g
"enum bitwise class foo {...}". With the current C++, one can probably
use template CRTP trick to avoid defining the operators separately for
each enum (I am not sure though that this will win "simplicity" points).

Cheers
Paavo



Paavo Helde

unread,
Nov 15, 2015, 6:44:25 PM11/15/15
to
jacobnavia <ja...@jacob.remcomp.fr> wrote in
news:n2b095$s50$1...@dont-email.me:
In C++ one can choose the exact level of complexity one wants. Literal
magic constants are valid C++ and have lots of drawbacks. The #define
constants are valid C++ and have lots of drawbacks. The enum constants
are valid C++ as well and have some drawbacks. Enum classes are valid C++
11 and have other kind of drawbacks (the complexity). In C++ one can
choose the needed level of safety-maintainability-simplicity as desired
all over the full scale, that's its bless and curse.

Short one-off hacks could best do with direct numeric literals, whereas
in large long-living projects robustness, safety, ease-of-maintenance
issues trump all other concerns like the effort of writing some more
lines for each enum. The thing is, one-off hacks can be written in any
language, most of which are simpler than C++, while for large long-living
projects C++ is one of the few truly viable options.

Cheers
Paavo



Öö Tiib

unread,
Nov 15, 2015, 7:30:46 PM11/15/15
to
On Monday, 16 November 2015 00:19:37 UTC+2, jacobnavia wrote:
> Le 15/11/2015 23:10, Vladislav Yaroslavlev a écrit :
> > First of all, it will not be implicitly converted to int. And it is great
>
> Sure. But if you want to use the enums as a bitfield;
>
> enum flags {
> Archived=1,
> Pending=2,
> Received=4,
> Sent=8,
> Forwarded=16
> };
>
> I can now say
>
> if (val &(Sent|Forwarded))
>
> to test for some bit.

Too cryptic.
I like it better to read as 'if (val[Sent] or val[Forwarded])'.
Code:

#include <bitset>
#include <iostream>

int main()
{
// Jacob's enum with magic numbers removed
enum DocState
{
Archived,
Pending,
Received,
Sent,
Forwarded,
Count_DocStates
};

// typedef the combined bitfield type DocStates
typedef std::bitset<Count_DocStates> DocStates;

// we have our bifield "val"
DocStates val;

// we can put some flags into it
val.set(Archived).set(Pending);

// Irrelevant crap that might be useful sometimes with such values
std::cout << "bitfield of val: " << val << '\r'
<< "number of bits: " << val.count() << '\r'
<< "val reversed: " << ~val << '\r';

// what Jacob wanted was
// if (val &(Sent|Forwarded))
// I consider it about as good to read
if (val[Sent] or val[Forwarded])
{
std::cout << "It was sent or forwarded \r";
}
else
{
std::cout << "It wasn't sent or forwarded \r";
}
}

Output:

bitfield of val: 00011
number of bits: 2
val reversed: 11100
It wasn't sent or forwarded

David Brown

unread,
Nov 15, 2015, 7:51:25 PM11/15/15
to
No, you are defining names for a set of bits - that is not the same as
an enumeration.

However, an "enum" is often the clearest and neatest way to achieve this
in C, and I think it is not unreasonable to do it that way.

You are right that a C++ enum class can't do that, because you can't
convert the enumeration constants to integers. Fair enough, a C++ enum
class won't cover that usage. But for more normal enumerations, an enum
class is a stronger and better scoped alternative to using the old, weak
enums. So in C++, use enum classes where possible, and old enums
otherwise. (Or use a selection of constexpr const's inside a class or
struct.)


Ian Collins

unread,
Nov 15, 2015, 9:05:40 PM11/15/15
to
jacobnavia wrote:
> Le 15/11/2015 23:37, Ian Collins a écrit :
>> Or provide the appropriate operator. One of the reasons for adding enum
>> class was to prevent inadvertent conversion to int. Given bit fields
>> are unsigned types, enum class allows you to specify the underlying
>> type. So you could still write:
>>
>> #include <stdint.h>
>>
>> enum class Bit : uint8_t { Zero = 1, One = 2 };
>>
>> bool operator | ( Bit b, uint8_t u )
>> {
>> return static_cast<uint8_t>(B) | u;
>> }
>>
>> bool operator | ( uint8_t u, Bit b )
>> {
>> return u | static_cast<uint8_t>(b);
>> }
>>
>> void f( uint8_t val )
>> {
>> Bit b;
>>
>> if( val | Bit::Zero )
>> {
>> }
>> }
>
>
> That's 13 lines of code to be done for each of those enums to do what
> plain enum gives me for free.

To be fair, the operators could be on one line and only one of them is
required for your example... So that's only one extra line (not to
mention your "13 lines" included an example!).

Most enum types don't require logical operators and they don't need to
be converted to int.

> Great Progress!

Indeed it is. Being able to specify the size of an enum type is
something that has been missing for way too long so has giving
enumerators their own scope.

> Look this is C++, I am no expert. I will just go on using enums...

Which is one of the beauties of C++: you have that choice.

--
Ian Collins

Martin Shobe

unread,
Nov 15, 2015, 11:17:50 PM11/15/15
to
Is everyone forgetting that you can overload the & operator (and friends)?

Martin Shobe

David Brown

unread,
Nov 16, 2015, 2:38:22 AM11/16/15
to
It's a balance between convenience and type safety. Yes, you /can/ make
an enum class and overload & and |, or perhaps make a conversion
operator to int. But that's quite a bit of extra coding compared to
simply using an old-fashioned enum. Is it really worth that extra
effort? With C++, you can choose either way - whatever makes most sense
for /your/ code.


Christian Gollwitzer

unread,
Nov 16, 2015, 4:54:31 AM11/16/15
to
Am 15.11.15 um 23:37 schrieb Ian Collins:
> jacobnavia wrote:
>> Le 15/11/2015 22:55, Ian Collins a écrit :
>>> If we leave aside the poor naming, the answer would be scope. Consider
>>> the case where you want to reuse enumeration names.
>>
>>
>> Is that a good idea?
>>
>>
>> Besides, very often I use enums as bitfields:
>>
>> enum foo{ property1=1,property2=2,property3=4,property4=8,property5=16};
>>
>> Then I can say
>> if (val & property5)
>>
>> That can't be done with scoped enums since there is no automatic
>> conversion to an integer. You would have to plaster your code with
>> static_cast<int>
>
> Or provide the appropriate operator. One of the reasons for adding enum
> class was to prevent inadvertent conversion to int. Given bit fields
> are unsigned types, enum class allows you to specify the underlying
> type.

This is still misusing enums for bitfields. There is a syntax for
bitfields in C++

struct foo {
bool sent : 1;
bool read : 1;
};

and then you can test for multiple conditions without the bitoperator hack:

foo x;

if (x.sent && x.read) { do_something(); }


I would expect that the compiler can optimize this to a bitoperation.

Christian



Martin Shobe

unread,
Nov 16, 2015, 9:26:34 AM11/16/15
to
As I tend to prefer the type safety, I do consider adding the couple of
lines of code needed worth the effort. I understand that others might
not consider it worth the effort and I'm find with that. My response was
intended to address the claim that, "a C++ enum class won't cover that
usage." (I also had read the other threads that mentioned the
possibility at that point.)

Martin Shobe

David Brown

unread,
Nov 16, 2015, 9:34:04 AM11/16/15
to
Fair enough. I should have written that a C++ enum class won't cover
that usage without additional code. (It is also possible to static_cast
the enum class element to an int or other underlying type directly in
the code. But that's ugly.)


Scott Lurndal

unread,
Nov 16, 2015, 9:41:53 AM11/16/15
to
Ian Collins <ian-...@hotmail.com> writes:
>Scott Lurndal wrote:
>> legaliz...@mail.xmission.com (Richard) writes:
>>> 1973.
>>>
>>> Modern C has enums and const integers as well, so even in C there is no
>>> excuse for using the preprocessor for named constants. See the C11 ISO
>>> standard; I consulted the April 12, 2011 committee draft.
>>
>> As has been pointed out to you repeatedly, not everyone can take
>> advantage of C11 and C++14. Nor do all real-word projects limit
>> themselves to a single language - it is not uncommon to mix C
>> and C++.
>
>I think you missed the point. In both C and C++ a better alternative to
>#defines for error codes exists and has existed for decades: a simple enum.
>

Although a simple enum is a signed integer. I'd prefer unsigned values
to be declared as unsigned and one can't do that with enum, unless one is
using C++11 or higher.

Gareth Owen

unread,
Nov 16, 2015, 12:59:03 PM11/16/15
to
jacobnavia <ja...@jacob.remcomp.fr> writes:

> enum flags {
> Archived=1,
> Pending=2,
> Received=4,
> Sent=8,
> Forwarded=16
> };

A naked enum is great for flags and lousy for type-safety.
An enum class is lousy for flags and great for type-safety.

In C++, use the one that fits your use case!
In C, use the one that exists!

Juha Nieminen

unread,
Nov 16, 2015, 4:41:04 PM11/16/15
to
JiiPee <n...@notvalid.com> wrote:
> #define ERROR_IN_INPUT 1
> #define TOO_LONG_INPUT 2
> #define PARAMETER_ERROR 3

Precompiler macros cannot be inside namespaces nor classes,
which means that they effectively contaminate the global
namespace in any file where they are declared.

Perhaps the most far-fetched reason for using macros instead
of constants is that the macro doesn't fix the type (which
sometimes is a bad thing, but in a few cases might in fact be
desirable.)

However, C++14 variable templates removed even that reason.
(And, in fact, variable templates are even better because you
can define the constant in different ways depending on the type,
and the correct definition will be chosen according to the use.)

--- news://freenews.netfront.net/ - complaints: ne...@netfront.net ---

Richard

unread,
Nov 19, 2015, 2:32:29 PM11/19/15
to
[Please do not mail me a copy of your followup]

Ben Bacarisse <ben.u...@bsb.me.uk> spake the secret code
<87pozdy...@bsb.me.uk> thusly:

>legaliz...@mail.xmission.com (Richard) writes:
><snip>
>> enum and const have been in C++ since the beginning. They do not
>> require C++14, C++11 or even C++03.
>>
>> I did a little bit of googling to find out when enums were formally
>> added to the C language, but wikipedia and other articles didn't give
>> a chronology.
>
>According to Dennis Ritchie:
>
> "During 1973-1980, the language grew a bit: the type structure gained
> unsigned, long, union, and enumeration types, and structures became
> nearly first-class objects (lacking only a notation for literals)."[1]

Nice; thanks for the research. So why are we arguing about avoiding
solutions that have been available for 35 years?
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>
0 new messages