#define - in header or cpp

C

Christopher

I don't use #defines myself, or very rarely. We are in the middle of a
style war and a coding style is being written up. Which brings the
topic of #define in preexisting code.

Obviously, #define directives the header needs will have to go in the
header. But what of all of the #defines that are used like constants?

example
#define MYSILLYSTRING "I'm a String"

When these are only used in a class' .cpp?

Should these go in the .h or the .cpp file? Reasoning?
 
V

Victor Bazarov

I don't use #defines myself, or very rarely. We are in the middle of a
style war and a coding style is being written up. Which brings the
topic of #define in preexisting code.

Obviously, #define directives the header needs will have to go in the
header. But what of all of the #defines that are used like constants?

example
#define MYSILLYSTRING "I'm a String"

When these are only used in a class' .cpp?

Should these go in the .h or the .cpp file? Reasoning?

Depends. If more than one source file uses such macros, they should
probably stay in *one place* so when there's a need to change the value,
you'd only go to one place to change it. The simplest example is some
kind of *version* designation that might be needed in both C++ and
*resource* files.

V
 
B

Balog Pal

Christopher said:
I don't use #defines myself, or very rarely. We are in the middle of a
style war and a coding style is being written up.

Reimplementing the wheel? Isn't the Sutter/Alexandrescu 101 book good enough
for your place?
Which brings the
topic of #define in preexisting code.

Obviously, #define directives the header needs will have to go in the
header. But what of all of the #defines that are used like constants?

example
#define MYSILLYSTRING "I'm a String"

When these are only used in a class' .cpp?

Should these go in the .h or the .cpp file? Reasoning?

1. header files are for shared stuff. what must be shared goes there. What
must not goes elsewhere.
2. #define is just for last resort -- use C++ native stuff wherever
possible.
3. where you are left with #define name it so it can not be confused with
anything else, and especially can not replace a part of existing code.
(like the evil GetMessage macro in windowsx.h)
4. If you have the strudy naming convintion from #3 it is no longer so
interesting where the macro was defined. So just use #1 for decision
5. use #undef for macros of short intended scope
 
C

Christopher

Reimplementing the wheel? Isn't the Sutter/Alexandrescu 101 book good enough
for your place?

If it was up to me. I just get to give limited input/arguments, if
that.

1. header files are for shared stuff. what must be shared goes there. What
must not goes elsewhere.
2. #define is just for last resort -- use C++ native stuff wherever
possible.
3. where you are left with #define name it so it can not be confused with
anything else, and especially can not replace a part of existing code.
(like the evil GetMessage macro in windowsx.h)
4. If you have the strudy naming convintion from #3 it is no longer so
interesting where the macro was defined. So just use #1 for decision
5. use #undef for macros of short intended scope

Good stuff. Thanks.
 
P

Paul Brettschneider

Balog said:
2. #define is just for last resort -- use C++ native stuff wherever
possible.

Somewhat off-topic: What is the C++-way of implementing string literal
macros for use with concetenation?

What I mean is this:

#define CONTROL_SEQUENCE "\xde\xad\xbe\xef"
static const char control_sequence[] = "\xde\xad\xbe\xef";
static const char *f1()
{
return "Test " CONTROL_SEQUENCE " string"; // Compiles but ugly
}
static const char *f2()
{
return "Test " control_sequence " string"; // Error
}

Thanks.
 
V

Victor Bazarov

Somewhat off-topic: What is the C++-way of implementing string literal
macros for use with concetenation?

It's a simple text replacement. There are no "string literal macros".
What I mean is this:

#define CONTROL_SEQUENCE "\xde\xad\xbe\xef"
static const char control_sequence[] = "\xde\xad\xbe\xef";
static const char *f1()
{
return "Test " CONTROL_SEQUENCE " string"; // Compiles but ugly

This is converted by the preprocessor into

return "Test " "\xde\xad\xbe\xef" " string";

(whitespace condenced, comments replaced with whitespace, macros are
replaced with their "values" - straight text substitution), and then the
adjacent string literals are concatenated (phase 6), so you get

return "Test \xde\xad\xbe\xef string";

just before the compiler gets that list of *tokens*.
}
static const char *f2()
{
return "Test " control_sequence " string"; // Error
}

There is no textual replacement here. It's a different list of tokens
the compiler gets:

return "Test " control_sequence " string";

in which no string literal appears in place of 'control_sequence' (which
is a variable name), and hence no concatenation occurs, and it's just a
syntax error after that.

Read about compilation stages in section 2.1 of the Standard. Macro
substitution is also described in section 16.3.

V
 
P

Paul Brettschneider

Hi,

Victor said:
Somewhat off-topic: What is the C++-way of implementing string literal
macros for use with concetenation?

It's a simple text replacement. There are no "string literal macros".
What I mean is this:

#define CONTROL_SEQUENCE "\xde\xad\xbe\xef"
static const char control_sequence[] = "\xde\xad\xbe\xef";
static const char *f1()
{
return "Test " CONTROL_SEQUENCE " string"; // Compiles but ugly

This is converted by the preprocessor into

return "Test " "\xde\xad\xbe\xef" " string";

(whitespace condenced, comments replaced with whitespace, macros are
replaced with their "values" - straight text substitution), and then the
adjacent string literals are concatenated (phase 6), so you get

return "Test \xde\xad\xbe\xef string";

just before the compiler gets that list of *tokens*.
}
static const char *f2()
{
return "Test " control_sequence " string"; // Error
}

There is no textual replacement here. It's a different list of tokens
the compiler gets:

return "Test " control_sequence " string";

in which no string literal appears in place of 'control_sequence' (which
is a variable name), and hence no concatenation occurs, and it's just a
syntax error after that.

Read about compilation stages in section 2.1 of the Standard. Macro
substitution is also described in section 16.3.

sorry for being unclear - I was well aware of all that. My question was if
there is a C++ replacement for this C-ism, which I happen to use quite
frequently. After all we're always told that macros (not type safe, side
effects) should be replaced by inline/template functions or const-
expressions. But I haven't figured out how to concatenate string literals
with const-expressions.

Thanks.
 
I

Ian Collins

Balog said:
2. #define is just for last resort -- use C++ native stuff wherever
possible.

Somewhat off-topic: What is the C++-way of implementing string literal
macros for use with concetenation?

What I mean is this:

#define CONTROL_SEQUENCE "\xde\xad\xbe\xef"
static const char control_sequence[] = "\xde\xad\xbe\xef";

static const std::string control_sequence = "\xde\xad\xbe\xef";
static const char *f1()
{
return "Test " CONTROL_SEQUENCE " string"; // Compiles but ugly
}
static const char *f2()
{
return "Test " control_sequence " string"; // Error
}

static std::string f2()
{
return "Test " + control_sequence + " string"; // No error
}
 
P

Paul Brettschneider

Ian said:
Balog said:
2. #define is just for last resort -- use C++ native stuff wherever
possible.

Somewhat off-topic: What is the C++-way of implementing string literal
macros for use with concetenation?

What I mean is this:

#define CONTROL_SEQUENCE "\xde\xad\xbe\xef"
static const char control_sequence[] = "\xde\xad\xbe\xef";

static const std::string control_sequence = "\xde\xad\xbe\xef";
static const char *f1()
{
return "Test " CONTROL_SEQUENCE " string"; // Compiles but ugly
}
static const char *f2()
{
return "Test " control_sequence " string"; // Error
}

static std::string f2()
{
return "Test " + control_sequence + " string"; // No error
}

Yes, you are right. And even that works:
#include <string>
#include <vector>
static const std::string control_sequence = "\xde\xad\xbe\xef";
const std::vector<std::string> messages = {
"Test " + control_sequence + " string",
"Test " + control_sequence + " string2",
"Test " + control_sequence + " string3"
};

I compared the code produced by g++ to

#define CONTROL_SEQUENCE "\xde\xad\xbe\xef"
const char *messages[] = {
"Test " CONTROL_SEQUENCE " string",
"Test " CONTROL_SEQUENCE " string2",
"Test " CONTROL_SEQUENCE " string3"
};

and the difference isn't pretty. :) Of course this may or may not be
relevant and smart compilers may produce much better code.
 
T

Thomas Boell

Balog said:
2. #define is just for last resort -- use C++ native stuff wherever
possible.

Somewhat off-topic: What is the C++-way of implementing string literal
macros for use with concetenation?

What I mean is this:

#define CONTROL_SEQUENCE "\xde\xad\xbe\xef"
static const char control_sequence[] = "\xde\xad\xbe\xef";

static const std::string control_sequence = "\xde\xad\xbe\xef";
static const char *f1()
{
return "Test " CONTROL_SEQUENCE " string"; // Compiles but ugly
}
static const char *f2()
{
return "Test " control_sequence " string"; // Error
}

static std::string f2()
{
return "Test " + control_sequence + " string"; // No error
}

Which is, of course, something totally different than Paul's
original example...

What is the problem with concatenating string literals at compile time,
anyway?
 
I

Ian Collins

Balog Pal wrote:

2. #define is just for last resort -- use C++ native stuff wherever
possible.

Somewhat off-topic: What is the C++-way of implementing string literal
macros for use with concetenation?

What I mean is this:

#define CONTROL_SEQUENCE "\xde\xad\xbe\xef"
static const char control_sequence[] = "\xde\xad\xbe\xef";

static const std::string control_sequence = "\xde\xad\xbe\xef";
static const char *f1()
{
return "Test " CONTROL_SEQUENCE " string"; // Compiles but ugly
}
static const char *f2()
{
return "Test " control_sequence " string"; // Error
}

static std::string f2()
{
return "Test " + control_sequence + " string"; // No error
}

Which is, of course, something totally different than Paul's
original example...

He asked for a C++ alternative to string literal concatenation, which is
what he got!
What is the problem with concatenating string literals at compile time,
anyway?

There isn't one.
 
P

Paul Brettschneider

Thomas said:
Balog Pal wrote:

2. #define is just for last resort -- use C++ native stuff wherever
possible.

Somewhat off-topic: What is the C++-way of implementing string literal
macros for use with concetenation?

What I mean is this:

#define CONTROL_SEQUENCE "\xde\xad\xbe\xef"
static const char control_sequence[] = "\xde\xad\xbe\xef";

static const std::string control_sequence = "\xde\xad\xbe\xef";
static const char *f1()
{
return "Test " CONTROL_SEQUENCE " string"; // Compiles but
ugly
}
static const char *f2()
{
return "Test " control_sequence " string"; // Error
}

static std::string f2()
{
return "Test " + control_sequence + " string"; // No error
}

Which is, of course, something totally different than Paul's
original example...

Hm, I would not say totally. But there clearly are differences which stem
from the fact POD vs. non-POD. For example this works:

#define CONTROL_SEQUENCE "\xde\xad\xbe\xef"
constexpr const char *f1()
{
return "Test " CONTROL_SEQUENCE " string";
}

while this doesn't:

static const std::string control_sequence = "\xde\xad\xbe\xef";
constexpr std::string f2()
{
return "Test " + control_sequence + " string",
}
// error: return type ‘std::string’ is not literal type

Interestingly, this *does* work:

static const std::string control_sequence = "\xde\xad\xbe\xef";
constexpr const char *f2()
{
static std::string s = "Test " + control_sequence + " string";
return s.c_str();
}

But the code is more ugly than the macro version.
What is the problem with concatenating string literals at compile time,
anyway?

Macros are evil. :) For example there is no scoping. I wish I could put
those control sequences inside a class, an enum or at least a namespace.
And I think it's curious that in times of templates where whole algorithms
are resolved at compile time, simple string literal concatenation is pushed
in the opposite direction from compile to runtime. Personally, I probably
will stay with the macro version, since it is not very intrusive and doesn't
have the usual problems of multiple evaluation of arguments, etc.

Thank you for all the comments so far.
 
G

gwowen

I don't use #defines myself, or very rarely. We are in the middle of a
style war and a coding style is being written up. Which brings the
topic of #define in preexisting code.

If you can't explain the reasons you're doing something -- and can't
come up with any reasons yourself -- why do you feel so strongly about
it that you're getting involved in a war over it?

Cargo cult programming is scary.
 
J

Joe Greer

Hm, I would not say totally. But there clearly are differences which
stem from the fact POD vs. non-POD. For example this works:

#define CONTROL_SEQUENCE "\xde\xad\xbe\xef"
constexpr const char *f1()
{
return "Test " CONTROL_SEQUENCE " string";
}

while this doesn't:

static const std::string control_sequence = "\xde\xad\xbe\xef";
constexpr std::string f2()
{
return "Test " + control_sequence + " string",
}
// error: return type ‘std::string’ is not literal type

Interestingly, this *does* work:

static const std::string control_sequence = "\xde\xad\xbe\xef";
constexpr const char *f2()
{
static std::string s = "Test " + control_sequence + " string";
return s.c_str();
}

But the code is more ugly than the macro version.


Macros are evil. :) For example there is no scoping. I wish I could
put those control sequences inside a class, an enum or at least a
namespace. And I think it's curious that in times of templates where
whole algorithms are resolved at compile time, simple string literal
concatenation is pushed in the opposite direction from compile to
runtime. Personally, I probably will stay with the macro version,
since it is not very intrusive and doesn't have the usual problems of
multiple evaluation of arguments, etc.

Thank you for all the comments so far.

The problem is that

static const std::string control_sequence = "\xde\xad\xbe\xef";

is not a literal. It is a constant object of type string and as such is limited by the interface
that a normal object is allowed to present. The compiler doesn't usually know anything special about
strings. By design, they are a library concern and not a compiler concern. Of course, since
std::string is standard, the compiler could know something and generate the code you want without any
special tricks, but that would be an optimization and you couldn't count on every compiler doing
that. On the otherhand, literals like "blah" are known by every compiler and provision is made in
the language such that "blah" "blech" can be combined by the compiler to "blahblech" at compile time.
As soon as you throw an object instance into mix (even a constant one), the compiler can't do much
with it because object instances provide runtime behavior and not compile time behavior. I haven't
really had an opportunity/need to use constexpr yet, but I suspect that the first doesn't work
because you are asking it to construct a new object each time. The second works because it can
create the string statically once and then just return its address. Have you considered just:

static const std::string control_sequence = "\xde\xad\xbe\xef";
static const std::string f2 = "Test " + control_sequence + " string";

That should work too. Of course, it's not trully generating a literal like the macros would, but
this would be evaluted once and reused everywhere. I doubt the runtime costs would be be measurable.

joe
 
J

Juha Nieminen

Christopher said:
Should these go in the .h or the .cpp file? Reasoning?

Why should it go in the header file?

A header file should only contain the bare minimum public interface of
the module it's representing. If the string constant in question is an
internal implementation detail of the module, putting it in the header
is horribly and absolutely *wrong*. It's the same as putting a private
variable in the public global namespace for absolutely no reason.
 
J

James Kanze

Reimplementing the wheel? Isn't the Sutter/Alexandrescu 101
book good enough for your place?

Not really. Despite its name, it doesn't address most of the
issues a coding guidelines should address.
1. header files are for shared stuff. what must be shared goes there. What
must not goes elsewhere.

And what isn't required to be shared shouldn't be.
2. #define is just for last resort -- use C++ native stuff wherever
possible.

Use #define where ever it's most appropriate. In general, I try
to avoid it in headers (except for the include guards), because
of the lack of scope, but I have no qualms about using it for
boilerplate code in the source files. (And of course, there are
cases where it is necessary: if you want to automatically insert
__LINE__ or __FILE__ somewhere, for example.)
3. where you are left with #define name it so it can not be confused with
anything else, and especially can not replace a part of existing code.
(like the evil GetMessage macro in windowsx.h)

Or String in X.h:). In a source file, rather than a header,
this is a bit less critical, but I still tend to favor it.

Also, once you no longer need the #define, use #undef to get rid
of it. (But I see you've mentionned that in point 5. It's
often overlooked.)
 
J

James Kanze

Thomas said:
What I mean is this:
#define CONTROL_SEQUENCE "\xde\xad\xbe\xef"
static const char control_sequence[] = "\xde\xad\xbe\xef";
static const std::string control_sequence = "\xde\xad\xbe\xef";
static const char *f1()
{
return "Test " CONTROL_SEQUENCE " string"; // Compiles but
ugly
}
static const char *f2()
{
return "Test " control_sequence " string"; // Error
}
static std::string f2()
{
return "Test " + control_sequence + " string"; // No error
}
Which is, of course, something totally different than Paul's
original example...
Hm, I would not say totally. But there clearly are differences which stem
from the fact POD vs. non-POD. For example this works:
#define CONTROL_SEQUENCE "\xde\xad\xbe\xef"
constexpr const char *f1()
{
return "Test " CONTROL_SEQUENCE " string";
}
while this doesn't:
static const std::string control_sequence = "\xde\xad\xbe\xef";
constexpr std::string f2()
{
return "Test " + control_sequence + " string",}
// error: return type ‘std::string’ is not literal type
Interestingly, this *does* work:
static const std::string control_sequence = "\xde\xad\xbe\xef";
constexpr const char *f2()
{
static std::string s = "Test " + control_sequence + " string";
return s.c_str();
}
But the code is more ugly than the macro version.

It also suffers from order of initialization problems. There
are still cases where a macro is the best solution.
Macros are evil. :)

Macros have a certain number of known defects. That doesn't
mean that they're never the best solution. (Try defining
something in the command line of the compiler, for example.
Like a version number.)
 
C

Christopher

If you can't explain the reasons you're doing something -- and can't
come up with any reasons yourself -- why do you feel so strongly about
it that you're getting involved in a war over it?

Cargo cult programming is scary.

I never said I felt strongly about it. "It" being the #define
placement. I feel very strongly about some of the other issues
involved in a coding standard, but they aren't mentioned in this post.
I am simply curious as to what guidelines there might already be,
since it is a topic that is part of a "coding standard." and a
standard is getting put into place.

I am involved, because whatever decisions get made as a whole will
effect my day to day work. I'd be silly not to be involved.
 
J

Jorgen Grahn

Why should it go in the header file?

A header file should only contain the bare minimum public interface of
the module it's representing. If the string constant in question is an
internal implementation detail of the module, putting it in the header
is horribly and absolutely *wrong*.

And it's worth pointing out that it's wrong.

I see fairly frequently people use the header file as if foo.h was
some kind of "table of contents" for foo.cc. Or as if it was "input
parameters" to foo.cc, so that anything you may want to tweak (magic
constants, buffer sizes, fixed file names) are in the header file.

People who do that have good intentions, but it's much more important
to minimize the "information load" on the global level.

/Jorgen
 
J

Juha Nieminen

Jorgen Grahn said:
I see fairly frequently people use the header file as if foo.h was
some kind of "table of contents" for foo.cc. Or as if it was "input
parameters" to foo.cc, so that anything you may want to tweak (magic
constants, buffer sizes, fixed file names) are in the header file.

To be fair, it's an interesting question that if you wanted a library
to be "customizable" at compile time, what would be the best design for
this. (These may be things that *must* be decided at compile time because
they can't be decided at runtime. For example dependence on some non-standard
library.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top