From: Carlos Moreno on

I'm wondering if it is possible to do the following, perhaps with
some
pre-processor trickery?

When providing a class, we usually provide a header file with the
class
declaration (and possibly some inline implementations), and an
implementation file.

My question is: is it possible for a given framework to require
users
of that framework (read: programmers that are using that framework
to create their applications) to provide certain specific methods
through
an implementation file, and *not* as inline methods in their class
declaration?

I'll be a little more specific as to what I need to do:

Following a discussion a while ago on the subject of "Automatic
Serialization", one of the aspects that came up was the need to
include in the programs some timestamp, so that if the program
is recompiled (indicating that the layout of the data for the class
may have changed), at run-time this can be known.

So, my framework provides a base class representing the application,
which is intended for users of the framework to derive from:

---- File application.h ----

class Application
{
public:
Application ()
: d_compile_timestamp ( __DATE__ __TIME__ )
{}

// ...
};

---- End File application.h ----


Users of the framework are supposed to create their file,
say, my_custom_app.h, with the following:

#include "application.h"

class My_custom_app : public Application
{
// customize things
};

The thing is, they will do this to create a customized "template"
for a set of applications --- that is, they will then derive from
My_custom_app to create multiple applicationss that are
specific instances of the "template" that they created.

But all of these specific instances of that template need to
be in sync with respect to the timestamp --- that is, the
executables corresponding to all of those need to be the
same for the system to work.

If they only provide a my_custom_app.h with the constructor
defined inline, then things won't work --- every time that they
compile each of the applications, those will get different
compile timestamps.

The only way it can work is if they provide a my_custom_app.c++
with the constructor defined in there --- and even then, that's
provided that they compile and link in multiple steps, and that
they don't unnecessarily recompile my_custom_app.c++ in
between compilations of the various applications.

So: is there a way for my framework to *require* that the
constructor for classes immediately derived from class
Application be defined through a .cpp file that is compiled
to an object file and later linked with the various applications?

Ideally, this would have to be a *pure C++* solution, and
preferably platform-independent --- if platform independent
is not possible, I would settle for a solution that works with
g++ on Linux.

Am I asking too much?

Thanks,

Carlos
--

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Sean Hunt on
On Jan 7, 8:55 am, Carlos Moreno <cm_n...(a)mailinator.com> wrote:
> class Application
> {
> public:
> Application ()
> : d_compile_timestamp ( __DATE__ __TIME__ )
> {}
>
> // ...
>
> };

This is actually illegal, since the definition of an inline function
must be identical in every file.

Sean

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Maciej Sobczak on
On 8 Sty, 23:40, Carlos Moreno <cm_n...(a)mailinator.com> wrote:

> your ieda of a very simple,
> possibly console-based or web-based application that simply creates
> the skeleton sounds nice.

Exactly - you don't need a full-blown IDE, nor any UML-based
machinery. Even XML style sheets are surprisingly powerful and with a
handful of Python/Perl/whatever scripts you can do miracles.

> Notice, however, that it does not handle
> the issue of the user manually compiling things --- if that file
> my_custom_app.c++ is recompiled by the user between compilations
> of custom_custom_app1 and custom_custom_app2, then these two are
> now out of sync.

You have mentioned something about Murphy and Machiavelli - what was
that, exactly? ;-)

Users don't compile things separately, they are too lazy. They just
type make and press enter. Just make sure that makefiles are in sync
with the rest, but this is easy to generate.
Laziness of the framework users is a key point here - if some choice
is already made for them (like the source file layout in this case),
they don't bother elaborating it. This nicely protects against Murphy.

--
Maciej Sobczak * www.msobczak.com * www.inspirel.com

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Greg Herlihy on
On Jan 7, 7:55 am, Carlos Moreno <cm_n...(a)mailinator.com> wrote:
>
> Following a discussion a while ago on the subject of "Automatic
> Serialization", one of the aspects that came up was the need to
> include in the programs some timestamp, so that if the program
> is recompiled (indicating that the layout of the data for the class
> may have changed), at run-time this can be known.
>
> So, my framework provides a base class representing the application,
> which is intended for users of the framework to derive from:
>
> ---- File application.h ----
>
> class Application
> {
> public:
> Application ()
> : d_compile_timestamp ( __DATE__ __TIME__ )
> {}
>
> // ...
>
> };

The Application class declaration above appears to violate C++'s "one
definition rule" (ODR) - specifically �3.2/5. The first bullet in that
paragraph requires that the definition of a class must - in each
translation unit in which the definition appears - consist of the same
sequence of tokens.

Yet the tokens that the preprocessor uses to replace __DATE__ and
__TIME__ do not remain constant from one translation unit to the next.
In fact,.because the date and time macros change so frequently, there
is effecitvely no way to ensure that Application's d_compile_timestamp
has a constant value initializer - let alone that d_compile_timestamp
will have the same a value in both a derived and its base class.

In short, using time stamps to track revisions to a class definition
is simply not a workable solution. Instead of relying on a continually-
changing time stamp value, the program really needs to find a value
that changes only upon each revision of the class header file itself.
Fortunately, there is at least one place where such a value can
usually be found: the source code control system (SCCS) that manages
the program's source code files. (And if, for some reason, the
program's soruce files are not under SCCS control, then the first step
is to check in those source files into an SCCS)

Most of the popular SCCS systems widely used today, including cvs,
subversion and perforce - can recognize something called "RCS
keywords" - special tokens placed in source files as stand-in for
values that the SCCS furnishes. So whenever the SCCS encounters one of
these RCS keywords in a file, the SCCS replaces the keyword with the
value that the keyword represents. (In this case, the RCS keyword of
interest is $Revision$, that is, the revision number of the header
file itself).

For example, an Application class definition that uses RCS keyword to
specify the value of the class version number, could look something
like this:

class Application
{
public:
Application ()
: d_class_version ( $Revision$ )
{}

// ...

};

Now, whenever a client checks out the "application.h" header file, the
SCCS will replace the $Revision$ keyword with the actual revision
number of Application.h itself. Furthermore, since the class version
number remains unchanged between class revisions, there is no need to
ban inline constructors in user-code (a requirement that was as
unenforceable as it was unreasonable in the first place.)

Naturally, the specific details of this proposed solution are likely
to vary somewhat - depending on the particular SCCS system in use. So,
it likely will be necessary to consult the relevant SCCS documentation
and to find which RCS keywords are recognized and what additional
steps (if any) must be taken RCS keywords to be recognized.

Greg



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]