Tuesday, March 31, 2015

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

legalize+jeeves@mail.xmission.com (Richard): Mar 31 10:11PM

[Please do not mail me a copy of your followup]
 
Joseph Hesse <joeh@gmail.com> spake the secret code
 
>1. In Funcs.cpp the file Funcs.h was included since it seems like best
>practices for an X.cpp to always include an X.h.
 
Historically, the linking model in C/C++ is such that if you reference a
symbol in a translation unit, the entire translation unit's object code
is added to your executable. This is a simplistic linkage model, but
explains why you see a function like strcmp implemented in its own
translation unit when you look at historical sources for the C
standard library. Each translation unit was considered a "module".
Symbols with static linkage weren't visible outside the module, but
symbols with extern linkage were visible to consumers of the module.
 
I haven't investigated, but I imagine that modern linkers look for dead
code that isn't referenced by anything else and eliminate it from the
final executable. That may only be performed in certain optimization
modes (whole program optimization?) and may not happen in a debug build.
 
In this sort of scenario it was common to have a single header file
for the library (think <stdio.h>) that was included by every module in
the library. In this case, the header files and source files didn't
have a one-to-one mapping. Libraries are composed of one or more
modules and declarations are made visible to clients with one or more
header files. (The C standard library contains more than just
<stdio.h> for instance.)
 
C++ has better means controlling visibility of symbols: namespaces,
visibility specifiers within a struct/class/union, etc. In a C++ code
base it is more common to break things up into small classes and
compose libraries as a collection of classes. It is fairly common to
have a one-to-one mapping between source files and headers in that a
single source file implements a single (small) class and the class is
declared for consumers in a single header file. There may be a
convenience header file for a library that aggregate multiple header
files together. (This is quite common in boost libraries.)
 
>argue that someone reading Funcs.cpp would see the use of the type
>vector<double> and therefore #include <vector> should also be there,
>even though it is redundant.
 
The general advice is that a header file should include everything
else needed for the declarations to compile. Therefore if you
reference std::vector<T> in some way in the header, you should include
<vector> in your header and not force the client to include <vector>
before including your header.
 
Further, if a source file uses something like std::vector, it should
include <vector>. The question in your example is whether or not
<vector> should appear in the header or just in the source file. If
you don't include <vector> in the header, then anyone who uses your
header must include <vector> *before* your header in order to use it.
This is placing a tax on users of Funcs.h that they must maintain. If
Funcs.h is later refactored to use some other container, or perhaps
not to use a container at all, then users of Funcs.h might be
including <vector> for no reason at all anymore. This is putting the
burden of maintenance in the wrong place. Include (or better, forward
declare) everything needed by your header file so that it stands
alone.
 
Some people write little test files in their build that look like this:
 
// TestFuncsHeader.cpp
#include "Funcs.h"
 
Their build system verifies that the header does indeed stand alone and
doesn't need any special magic in order to be used in isolation.
 
The philosophy behind the "include what you use" utility says that you
should include headers for everything you use in your source file:
<https://code.google.com/p/include-what-you-use/>
 
Their rationale for why you should do this is on their wiki:
<https://code.google.com/p/include-what-you-use/wiki/WhyIWYU>
 
So in this case, <vector> belongs in Funcs.h and is redundant in its
companion implementation file Funcs.cpp
 
>2. Same question for Test.cpp. Should #include <vector> be there since
>it already comes from #include Funcs.h?
 
If the only reason std::vector is used in Test.cpp is from the
callsites to code in Funcs.h, then I'd say no. When Test.cpp is
designed to test the implementation in Funcs.cpp, this is the clear
'no' case.
 
When a source file consumes functionality from Funcs.h, but also has
it's own code that uses std::vector outside of the API of Funcs.h,
then I would include <vector> in the source file. Eventually the
stuff using Funcs.h may split off this source file or switch to use
another API (or version of Funcs.h) that doesn't use std::vector, but
the source file still has its own need for std::vector. Then you want
to include <vector> in that source file, even though Funcs.h included
it already.
--
"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>
Richard Damon <Richard@Damon-Family.org>: Mar 30 09:42PM -0400

On 3/30/15 4:42 PM, Vir Campestris wrote:
 
> But there was no STL way to say "What's my char set" or "set my char
> set" - so you're down to implementation dependent stuff.
 
> Andy
 
My feeling is why would a program embed a non-basic-character set
filename in itself anyway, and need to avoid implementation dependent
stuff? Almost always, if I need to access a filename like that, it has
come from somewhere else. If I need to hard code a filename, I will use
just the basic alpha-numerics so it is safe.
 
Just by assuming you CAN use such a file name is a big assumption, and
makes you program implementation dependent to begin with.
 
Note, that you CAN get information about the current language, by using
setlocale and passing a null pointer for the locale information, but the
encoding of the results is implementation dependent.
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: