Can static member variables be declared "inline"?

Discussion in 'C++' started by Juha Nieminen, Sep 1, 2008.

  1. As we know, the keyword "inline" is a bit misleading because its
    meaning has changed in practice. In most modern compilers it has
    completely lost its meaning of "a hint for the compiler to inline the
    function if possible" (because if the compiler has the function
    definition available at an instantiation point, it will estimate whether
    to inline it or not, and do so if it estimates it would be beneficial,
    completely regardless of whether the keyword 'inline' appears in the
    function definition or not).

    In fact, the keyword "inline" is in practice a linker command, not a
    compiler command. It tells the linker that if it finds an instantiation
    of that function in more than one object file, it should use only one of
    them and discard the rest.

    Also as we know, template functions and member functions of template
    classes are implicitly "inline": If they are instantiated in more than
    one compilation unit (and not inlined), the linker will use only one
    instantiation when linking and discard the rest.

    What many C++ programmers might not realize is that this implicit
    inlining of template class members extends to static member variables as
    well. In other words, if you do this:

    // Template class header file
    // --------------------------------------------
    template<typename T>
    class SomeClass
    {
    static int memberVariable;
    ...
    };

    template<typename T>
    int SomeClass<T>::memberVariable = 1;
    // --------------------------------------------

    and this header is used in more than one compilation unit, the static
    member variable will also be instantiated in all those compilation
    units, but this will not cause a linker error. The linker will nicely
    use only one of them and discard the rest. Effectively the static member
    variable has been declared "inline".

    This is not only a nice feature of template classes, but a must.
    Without this property it would be impossible to have static member
    variables in template classes because it would be impossible to
    instantiate them in only one place (if the template class is used in
    more than one compilation unit).

    So my question is: Why can't static member variables of regular
    classes be declared "inline", like the ones of template classes?
    Compilers clearly have the support for this because they must do it for
    template classes. However, seemingly the C++ standard does not support
    this for static members of regular classes. Or is there a way that I
    don't know of?
     
    Juha Nieminen, Sep 1, 2008
    #1
    1. Advertising

  2. Juha Nieminen

    James Kanze Guest

    On Sep 2, 12:26 am, Juha Nieminen <> wrote:
    > As we know, the keyword "inline" is a bit misleading because
    > its meaning has changed in practice. In most modern compilers
    > it has completely lost its meaning of "a hint for the compiler
    > to inline the function if possible" (because if the compiler
    > has the function definition available at an instantiation
    > point, it will estimate whether to inline it or not, and do so
    > if it estimates it would be beneficial, completely regardless
    > of whether the keyword 'inline' appears in the function
    > definition or not).


    Unless the compiler can be reasonably sure of making a better
    estimate than you, I'd call this a bug, or at least poor quality
    of implementation. And only a very few compilers are capable of
    this except in very limited cases.

    > In fact, the keyword "inline" is in practice a linker command,
    > not a compiler command.


    It's not a command, it's a "function specifier", which is in
    some ways a bit like a "storage class specifier". It's a part
    of the language, and has a specific semantic associated with the
    language (it makes multiple definitions legal, provided that
    they are in different sources). It also has an "intent", and it
    is a poor compiler which ignores this intent (unless, as I said,
    it is certain that it can do better).

    > It tells the linker that if it finds an instantiation of that
    > function in more than one object file, it should use only one
    > of them and discard the rest.


    No. That's one aspect of some implementations, but it's not
    fundamental. (And a compiler could do this with non-inline
    functions as well, if it wanted to.)

    > Also as we know, template functions and member functions of
    > template classes are implicitly "inline":


    No they're not, although they can also be multiply defined (and
    you're forgetting export, of course).

    > If they are instantiated in more than one compilation unit
    > (and not inlined), the linker will use only one instantiation
    > when linking and discard the rest.


    Again, implementation defined. I've used compilers that didn't
    instantiate any of the template functions until link time, and
    then only once.

    > What many C++ programmers might not realize is that this
    > implicit inlining of template class members extends to static
    > member variables as well. In other words, if you do this:


    > // Template class header file
    > // --------------------------------------------
    > template<typename T>
    > class SomeClass
    > {
    > static int memberVariable;
    > ...
    > };


    > template<typename T>
    > int SomeClass<T>::memberVariable = 1;
    > // --------------------------------------------


    > and this header is used in more than one compilation unit, the
    > static member variable will also be instantiated in all those
    > compilation units, but this will not cause a linker error.


    Again, that's one way (not the best, but probably the most
    widespread) of implementing this. It's certainly not required
    by the standard.

    > The linker will nicely use only one of them and discard the
    > rest. Effectively the static member variable has been
    > declared "inline".


    > This is not only a nice feature of template classes, but a
    > must. Without this property it would be impossible to have
    > static member variables in template classes because it would
    > be impossible to instantiate them in only one place (if the
    > template class is used in more than one compilation unit).


    > So my question is: Why can't static member variables of
    > regular classes be declared "inline", like the ones of
    > template classes?


    Because "the inline specifier indicates to the implementation
    that inline substitution of the function body at the point of
    call is to be preferred to the usual function call mechanism."
    Which obviously doesn't make sense for variables. And "while an
    implementation is not required to perform this inline
    substitution", the intent is clearly expressed, and it would be
    a very poor implementation which didn't perform it without a
    very good reason for not doing so.

    > Compilers clearly have the support for this because they must
    > do it for template classes. However, seemingly the C++
    > standard does not support this for static members of regular
    > classes. Or is there a way that I don't know of?


    Make the class a template:).

    Seriously, why do you want to do it?

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Sep 2, 2008
    #2
    1. Advertising

  3. James Kanze wrote:
    [treat "inline" as "the definition is inlined into the interface"]

    > Seriously, why do you want to do it?


    Header-only implementations of libraries (with globals) would be an
    application.
     
    Marco Manfredini, Sep 2, 2008
    #3
  4. Juha Nieminen

    cch@srdgame Guest

    于 Mon, 01 Sep 2008 22:26:08 +0000,Juha Nieminen写到:

    > As we know, the keyword "inline" is a bit misleading because its meaning
    > has changed in practice. In most modern compilers it has completely lost
    > its meaning of "a hint for the compiler to inline the function if
    > possible" (because if the compiler has the function definition available
    > at an instantiation point, it will estimate whether to inline it or not,
    > and do so if it estimates it would be beneficial, completely regardless
    > of whether the keyword 'inline' appears in the function definition or
    > not).
    >
    > In fact, the keyword "inline" is in practice a linker command, not a
    > compiler command. It tells the linker that if it finds an instantiation
    > of that function in more than one object file, it should use only one of
    > them and discard the rest.
    >
    > Also as we know, template functions and member functions of template
    > classes are implicitly "inline": If they are instantiated in more than
    > one compilation unit (and not inlined), the linker will use only one
    > instantiation when linking and discard the rest.
    >
    > What many C++ programmers might not realize is that this implicit
    > inlining of template class members extends to static member variables as
    > well. In other words, if you do this:
    >
    > // Template class header file
    > // -------------------------------------------- template<typename T>
    > class SomeClass
    > {
    > static int memberVariable;
    > ...
    > };
    >
    > template<typename T>
    > int SomeClass<T>::memberVariable = 1; //
    > --------------------------------------------
    >
    > and this header is used in more than one compilation unit, the static
    > member variable will also be instantiated in all those compilation
    > units, but this will not cause a linker error. The linker will nicely
    > use only one of them and discard the rest. Effectively the static member
    > variable has been declared "inline".
    >
    > This is not only a nice feature of template classes, but a must.
    > Without this property it would be impossible to have static member
    > variables in template classes because it would be impossible to
    > instantiate them in only one place (if the template class is used in
    > more than one compilation unit).
    >
    > So my question is: Why can't static member variables of regular
    > classes be declared "inline", like the ones of template classes?
    > Compilers clearly have the support for this because they must do it for
    > template classes. However, seemingly the C++ standard does not support
    > this for static members of regular classes. Or is there a way that I
    > don't know of?


    The one you decalared in template is not inline, even it is in hearder
    file.

    The template will be extracted to regular classes whenever you use
    SomeClass<type>. Different "type" will be extracted to different class.

    BTW: I only heard about inline function, but not inline variables.

    --
    cch@srdgame
     
    cch@srdgame, Sep 2, 2008
    #4
  5. Alf P. Steinbach wrote:
    > * James Kanze:
    >>
    >> Seriously, why do you want to do it?

    >
    > Practically, for the purpose of header-only code.


    Right. If you make a very small utility class which, for example, you
    want to distribute, it makes the usage of that utility much easier when
    you can simply say "unpack this file into your source directory, and
    then just #include it wherever you need it; nothing else is needed".

    If the class happens to need a static member variable, then there's no
    way around it: You must provide a source file (which might only contain
    the definition of that static member variable and nothing else), and the
    user will have to include this source file into his project or makefile
    (or compile it separately). Sure, it's not that big of a deal, but adds
    useless complication to such a small utility class, and can be a
    nuisance for very small one-source-file programs.

    But I suppose a trick around the problem is to indeed make the class a
    template class and then create the actual type with a typedef. Perhaps
    something like:

    template<int i>
    class TemplatedVersionOfTheClass
    {
    ...
    };

    typedef TemplatedVersionOfTheClass<0> TheClass;

    (In fact, this might even make it more efficient because only those
    member functions which are really used will end up in the final
    executable file. With regular classes all the member functions may well
    end up there, even though some of them might never be called.)

    Of course, depending on the compiler, error messages can get uglier.
     
    Juha Nieminen, Sep 2, 2008
    #5
  6. cch@srdgame wrote:
    > The one you decalared in template is not inline, even it is in hearder
    > file.
    >
    > The template will be extracted to regular classes whenever you use
    > SomeClass<type>. Different "type" will be extracted to different class.


    Wrong. Even if the same static member variable is instantiated in more
    than one compilation unit (because both use the template class with the
    same template parameters), the linker will use only one of those
    instantiations and will not give an error because of multiple
    definitions. This works in the same way as inline functions (which don't
    actually get inlined).
     
    Juha Nieminen, Sep 2, 2008
    #6
  7. Juha Nieminen

    James Kanze Guest

    On Sep 2, 1:06 pm, Marco Manfredini <> wrote:
    > James Kanze wrote:


    > [treat "inline" as "the definition is inlined into the interface"]


    > > Seriously, why do you want to do it?


    > Header-only implementations of libraries (with globals) would
    > be an application.


    But why would you want to do that? If your code is all
    templates, you may have to, but it's really something which
    you'd want to avoid, no?

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Sep 2, 2008
    #7
  8. Juha Nieminen

    James Kanze Guest

    On Sep 2, 2:40 pm, "Alf P. Steinbach" <> wrote:
    > * James Kanze:


    > > On Sep 2, 12:26 am, Juha Nieminen <> wrote:


    > >> So my question is: Why can't static member variables of
    > >> regular classes be declared "inline", like the ones of
    > >> template classes?


    > > Because "the inline specifier indicates to the implementation
    > > that inline substitution of the function body at the point of
    > > call is to be preferred to the usual function call mechanism."
    > > Which obviously doesn't make sense for variables.


    > In other words, the standard contains this wording because it
    > contains this wording?


    The standard contains this wording because inline expresses an
    intent which only makes sense for functions, not for variables.

    > If you really meant that then it would be meaningless.


    > But I think you misunderstood Juha's point.


    > The simple answer is, historic accident.


    > 'inline' came first, templates came later, and the joining
    > wasn't perfect, just practical enough to be useful.


    I'm pretty sure that that's not true. It's more or less an
    (unfortunate) accident that templates work more or less like
    inline does, and it was certainly never the intent to require
    this, or ban more efficient (for the programmer)
    implementations. And inline was always viewed more or less like
    register, in the old days: an ugly hack, necessary because
    compiler technology wasn't adequate to figure it out better than
    the programmer. Probably, in ten years time, or more, inline
    will be considered much like register is today---and be more or
    less ignored. But we aren't there yet: inline is your way of
    telling the compiler that the function will be called very, very
    often, and that the execution time of the actual call will be
    significant in the total runtime of the program. And that just
    doesn't make sense for variables.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Sep 2, 2008
    #8
  9. Juha Nieminen

    James Kanze Guest

    On Sep 2, 4:22 pm, Juha Nieminen <> wrote:
    > cch@srdgame wrote:
    > > The one you decalared in template is not inline, even it is in hearder
    > > file.


    > > The template will be extracted to regular classes whenever you use
    > > SomeClass<type>. Different "type" will be extracted to different class..


    > Wrong.


    I don't think English is cch's native language, and his
    expression isn't the clearest, but what he says is 100% correct
    (although not necessarily very relevant to the issue at hand).

    > Even if the same static member variable is instantiated in more
    > than one compilation unit (because both use the template class with the
    > same template parameters),


    Except that he explicitly said that the "type" were different.

    > the linker will use only one of those instantiations and will
    > not give an error because of multiple definitions. This works
    > in the same way as inline functions (which don't actually get
    > inlined).


    And you seem to be confusing what the standard says about
    "instantiation" and how some (not all) compilers happen to
    implement it. As far as the standard is concerned, for any
    given set of template arguments, instantiation takes place once,
    and only once. Where exactly (in which of the various contexts
    which triggered the instantiation) is not defined, and if the
    results of the instantiation depend on where, the program has
    undefined behavior, but there is one, and only one
    instantiation. Some compilers do instantiate many times, and
    count on the linker throwing out all but one, but the better
    ones maintain a repository of some sort, and don't reinstantiate
    if they don't have to. (Of course, getting this right is
    non-trivial, and earlier versions often failed to reinstantiate
    when they should have, or vice version, which has left a bad
    taste in some people's mouth. But correctly implemented, it's
    far superior than redoing the work n times, with n copies of the
    same thing floating around.)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Sep 2, 2008
    #9
  10. James Kanze wrote:

    > On Sep 2, 1:06 pm, Marco Manfredini <> wrote:
    >> James Kanze wrote:

    >
    >> [treat "inline" as "the definition is inlined into the interface"]

    >
    >> > Seriously, why do you want to do it?

    >
    >> Header-only implementations of libraries (with globals) would
    >> be an application.

    >
    > But why would you want to do that? If your code is all
    > templates, you may have to, but it's really something which
    > you'd want to avoid, no?


    Having the implementation and interface in one file is really handy,
    because you don't have to maintain the build of the implementation file
    (or even a separate library) anymore. Also it simplifies code sharing
    between libraries or shared objects, because you are untroubled by
    duplicate definition problems. Also, deployment is trivial and binary
    compatibility a non-issue.
     
    Marco Manfredini, Sep 2, 2008
    #10
  11. James Kanze wrote:
    > Some compilers do instantiate many times, and
    > count on the linker throwing out all but one, but the better
    > ones maintain a repository of some sort, and don't reinstantiate
    > if they don't have to.


    That would depend a lot on the compilation strategy used.

    Classically each compilation unit (eg. .cc file) is compiled
    completely separately and independently into an object file (eg. .o).
    That's everything the compiler might be instructed to do: To compile one
    ..cc file into one .o file, period. The compiler does not know of
    anything else. This is the most typical situation when compiling with
    makefiles and the 'make' utility.

    In this case the compiler has absolutely no way of knowing where else
    some templated static variable might be used, so it simply has no other
    option than to instantiate it in that object file. It knows of no
    others. It can't even know what the object file will be used for. Maybe
    it will not be used to link an executable directly, but rather create a
    precompiled library (.a or .lib in many system) or a
    dynamically-linkable one (.so, .dll). In theory the object file could
    even be used to link it to a program written in a completely different
    language (although only in theory, as in practice this happens quite
    rarely). So in short, it has no other option than to make the
    instantiation to the object file.

    Is this an "inferior" compiler in your opinion? Because you talk about
    other compilers which use a different compilation strategy as "better".
     
    Juha Nieminen, Sep 2, 2008
    #11
  12. Juha Nieminen

    Ian Collins Guest

    James Kanze wrote:
    > Some compilers do instantiate many times, and
    > count on the linker throwing out all but one, but the better
    > ones maintain a repository of some sort, and don't reinstantiate
    > if they don't have to. (Of course, getting this right is
    > non-trivial, and earlier versions often failed to reinstantiate
    > when they should have, or vice version, which has left a bad
    > taste in some people's mouth.


    "vice version" - I like it!

    > But correctly implemented, it's
    > far superior than redoing the work n times, with n copies of the
    > same thing floating around.)
    >

    That may or my not be true. In a distributed build environment,
    obtaining and waiting for locks on a repository may impede progress more
    than simply redoing the work n times. Some degree of duplication
    removal will be required non-inlined copies of inline methods.

    --
    Ian Collins.
     
    Ian Collins, Sep 2, 2008
    #12
  13. Juha Nieminen

    Ian Collins Guest

    Juha Nieminen wrote:
    > James Kanze wrote:
    >> Some compilers do instantiate many times, and
    >> count on the linker throwing out all but one, but the better
    >> ones maintain a repository of some sort, and don't reinstantiate
    >> if they don't have to.

    >
    > That would depend a lot on the compilation strategy used.
    >
    > Classically each compilation unit (eg. .cc file) is compiled
    > completely separately and independently into an object file (eg. .o).
    > That's everything the compiler might be instructed to do: To compile one
    > ..cc file into one .o file, period. The compiler does not know of
    > anything else. This is the most typical situation when compiling with
    > makefiles and the 'make' utility.
    >

    Some compilers (Sun CC was one) used or still use a template repository
    where each instantiation of a template has its own object file. These
    are resolved just like "regular" object files at link time.

    > In this case the compiler has absolutely no way of knowing where else
    > some templated static variable might be used, so it simply has no other
    > option than to instantiate it in that object file.


    Exactly - that might be a specific object for for that instantiation.

    > It knows of no
    > others. It can't even know what the object file will be used for. Maybe
    > it will not be used to link an executable directly, but rather create a
    > precompiled library (.a or .lib in many system) or a
    > dynamically-linkable one (.so, .dll). In theory the object file could
    > even be used to link it to a program written in a completely different
    > language (although only in theory, as in practice this happens quite
    > rarely). So in short, it has no other option than to make the
    > instantiation to the object file.
    >

    Object file or files. There is nothing in the standard that mandates a
    one to one mapping between compilation units and object files. I don't
    recall even seeing mention of object files.

    > Is this an "inferior" compiler in your opinion? Because you talk about
    > other compilers which use a different compilation strategy as "better".


    A subjective opinion!

    --
    Ian Collins.
     
    Ian Collins, Sep 2, 2008
    #13
  14. Juha Nieminen

    James Kanze Guest

    On Sep 2, 6:31 pm, Marco Manfredini <> wrote:
    > James Kanze wrote:
    > > On Sep 2, 1:06 pm, Marco Manfredini <> wrote:
    > >> James Kanze wrote:


    > >> [treat "inline" as "the definition is inlined into the interface"]


    > >> > Seriously, why do you want to do it?


    > >> Header-only implementations of libraries (with globals) would
    > >> be an application.


    > > But why would you want to do that? If your code is all
    > > templates, you may have to, but it's really something which
    > > you'd want to avoid, no?


    > Having the implementation and interface in one file is really
    > handy, because you don't have to maintain the build of the
    > implementation file (or even a separate library) anymore. Also
    > it simplifies code sharing between libraries or shared
    > objects, because you are untroubled by duplicate definition
    > problems. Also, deployment is trivial and binary compatibility
    > a non-issue.


    Which is all fine for toy projects, but anytime you modify a
    header, you have to recompile all of the client code. So you
    want as little as possible in the header---ideally, only the
    API definitions. (Why do you think the compilation firewall
    idiom is so popular?)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Sep 3, 2008
    #14
  15. Juha Nieminen

    James Kanze Guest

    On Sep 2, 9:14 pm, Juha Nieminen <> wrote:
    > James Kanze wrote:
    > > Some compilers do instantiate many times, and
    > > count on the linker throwing out all but one, but the better
    > > ones maintain a repository of some sort, and don't reinstantiate
    > > if they don't have to.


    > That would depend a lot on the compilation strategy used.


    Exactly.

    > Classically each compilation unit (eg. .cc file) is compiled
    > completely separately and independently into an object file
    > (eg. .o).


    And classically, the implementation code of the template was in
    a separate source file, which didn't get read (and compiled)
    until link time.

    > That's everything the compiler might be instructed to do: To
    > compile one .cc file into one .o file, period.


    That's a fairly rare case today. I don't know of any compiler
    which supports templates which uses it. Compilers output a
    variety of files, for a variety of different reasons.

    > The compiler does not know of anything else. This is the most
    > typical situation when compiling with makefiles and the 'make'
    > utility.


    It's not the situation with Sun CC, under Solaris. It wasn't
    the situation with the old CC under HP/UX, either. (I've not
    had the occasion to see what the newer aCC does). And if memory
    serves me right (it's been a long time), it wasn't the case with
    the old xlC compilers under AIX, and from what I've heard, it
    isn't the case with IBM's Visual Age compilers either.

    In fact, the only compiler I know which does it this way is g++,
    and even then, there are options and variants which change it.
    VC++ generates tons of additional files, but I don't think they
    have anything to do with templates, so conceptually, VC++ is
    probably similar to g++. Sun CC, HP's old CC and Visual Age CC
    all use some form of repository, and cache instantiations.

    > In this case the compiler has absolutely no way of knowing
    > where else some templated static variable might be used, so it
    > simply has no other option than to instantiate it in that
    > object file.


    It can look in the repository, and see if the template has been
    instantiated with the given arguments or not. If it hasn't
    been, the compiler instantiates it and adds the instantiation to
    the repository (and NOT to the object file).

    This is the way templates "classically" worked.

    > It knows of no others. It can't even know what the object file
    > will be used for. Maybe it will not be used to link an
    > executable directly, but rather create a precompiled library
    > (.a or .lib in many system) or a dynamically-linkable one
    > (.so, .dll). In theory the object file could even be used to
    > link it to a program written in a completely different
    > language (although only in theory, as in practice this happens
    > quite rarely). So in short, it has no other option than to
    > make the instantiation to the object file.


    Which is why most compilers don't.

    > Is this an "inferior" compiler in your opinion?


    In this regard, yes. (Obviously, other issues come into play,
    and globally, g++'s support for templates is better than that in
    Sun CC. But the compilation model used by Sun is far better.)

    > Because you talk about other compilers which use a different
    > compilation strategy as "better".


    Well, using some sort of repository seems like a much better
    solution, if done correctly. And most of the compilers I've
    used have used a repository---g++ and VC++ are the notable
    exceptions.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Sep 3, 2008
    #15
  16. Juha Nieminen

    James Kanze Guest

    On Sep 2, 9:15 pm, Ian Collins <> wrote:
    > James Kanze wrote:
    > > Some compilers do instantiate many times, and
    > > count on the linker throwing out all but one, but the better
    > > ones maintain a repository of some sort, and don't reinstantiate
    > > if they don't have to. (Of course, getting this right is
    > > non-trivial, and earlier versions often failed to reinstantiate
    > > when they should have, or vice version, which has left a bad
    > > taste in some people's mouth.


    > "vice version" - I like it!


    A Freudian slip for vice versa, of course. But you've revealed
    enough personal data in other postings for me to suspect that
    you've some experience with early CFront based implementations
    of templates (any of the Sun CC 3.x, for example), so you know
    what I'm talking about: any unexplained error, and you zap the
    repository and rebuild from scratch. (The files in the
    repository weren't known to make, and the compiler didn't manage
    its dependencies correctly---IIRC, it didn't look beyond the
    first level of includes. Part of this was doubtlessly due to
    the fact that all of the files in the repository had a
    "standard" format: C++ source or object format, so the compiler
    couldn't maintain all of the additional necessary information it
    needed.)

    > > But correctly implemented, it's far superior than redoing
    > > the work n times, with n copies of the same thing floating
    > > around.)


    > That may or my not be true. In a distributed build
    > environment, obtaining and waiting for locks on a repository
    > may impede progress more than simply redoing the work n times.
    > Some degree of duplication removal will be required
    > non-inlined copies of inline methods.


    That may be a point, and it's certainly relevant to the way Sun
    implements its repository. But that sounds like a problem in
    the implementation, and not something fundamental. If the
    repository were in an Oracle database, for example, I doubt that
    you'd find much slow down.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Sep 3, 2008
    #16
  17. Juha Nieminen

    Ian Collins Guest

    James Kanze wrote:
    >
    > But you've revealed
    > enough personal data in other postings for me to suspect that
    > you've some experience with early CFront based implementations
    > of templates (any of the Sun CC 3.x, for example), so you know
    > what I'm talking about: any unexplained error, and you zap the
    > repository and rebuild from scratch.


    Indeed I do, I paid about 1500 pounds for a copy!

    >>> But correctly implemented, it's far superior than redoing
    >>> the work n times, with n copies of the same thing floating
    >>> around.)

    >
    >> That may or my not be true. In a distributed build
    >> environment, obtaining and waiting for locks on a repository
    >> may impede progress more than simply redoing the work n times.
    >> Some degree of duplication removal will be required
    >> non-inlined copies of inline methods.

    >
    > That may be a point, and it's certainly relevant to the way Sun
    > implements its repository. But that sounds like a problem in
    > the implementation, and not something fundamental. If the
    > repository were in an Oracle database, for example, I doubt that
    > you'd find much slow down.
    >

    As machines processing speed increases way faster than network speed,
    anything that adds network writes is going to cause issues.

    --
    Ian Collins.
     
    Ian Collins, Sep 3, 2008
    #17
  18. James Kanze wrote:

    > On Sep 2, 6:31 pm, Marco Manfredini <> wrote:
    >> Having the implementation and interface in one file is really
    >> handy, because you don't have to maintain the build of the
    >> implementation file (or even a separate library) anymore. Also
    >> it simplifies code sharing between libraries or shared
    >> objects, because you are untroubled by duplicate definition
    >> problems. Also, deployment is trivial and binary compatibility
    >> a non-issue.

    >
    > Which is all fine for toy projects, but anytime you modify a
    > header, you have to recompile all of the client code. So you
    > want as little as possible in the header---ideally, only the
    > API definitions. (Why do you think the compilation firewall
    > idiom is so popular?)


    The compilation firewall is popular, because there are Projects which
    have a evolving, non-trivial implementation, but a fixed API. However,
    there are also Projects with a trivial implementation and an evolving
    interface - one example would be library/OS-syscall wrappers which
    translate something from the "C" domain into a edible form (RAII,
    typesafety, stl-adapter, exceptions...). There is no point in
    maintaining a stable API, because the implementation is very unlikely
    to change, which gives us the opportunity to evolve the interface as
    needed, because the only one to upgrade to a new version is the one who
    needs the new interface features anyway.

    As a negative example, take the cairomm library, which is a wrapper
    around the cairo-API, The encapsulation dogma is strong within their
    maintainers and so they decided, that cairo_rotate must be wrapped as:

    in the public header file:
    ---------------------------------------------
    #include <cairo.h>
    ....
    class Cairo {
    ....
    void rotate(double angle_radians);
    void rotate_degrees(double angle_radians);
    ...
    }
    ---------------------------------------------

    in the implementation file:
    ---------------------------------------------
    void Context::rotate(double angle_radians)
    {
    cairo_rotate(m_cobject, angle_radians);
    check_object_status_and_throw_exception(*this);
    }
    void Context::rotate_degrees(double angle_degrees)
    {
    cairo_rotate(m_cobject, angle_degrees * M_PI/180.0);
    check_object_status_and_throw_exception(*this);
    }
    ---------------------------------------------
    Note the contempt for code reuse.

    So basically, when I want to use cairomm, I have to dig into pkg-config
    to find *the right shared library for my target platform* (multiarch!
    cross-compile!) and when I run the program I need the runtime linker to
    load it and relocate all calls into it. And I can't run my binary on a
    system where cairomm is missing or, let's say, does not implement
    rotate_degrees yet. I've got tangled up with a completely unnecessary
    fill features library, which could have been implemented header only
    instead.
     
    Marco Manfredini, Sep 3, 2008
    #18
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. JohnZing

    declared or not declared ?

    JohnZing, Feb 5, 2006, in forum: ASP .Net
    Replies:
    3
    Views:
    1,619
    Jon Paal
    Feb 5, 2006
  2. Sean
    Replies:
    4
    Views:
    693
    Rolf Magnus
    Apr 30, 2006
  3. Martin Wells

    Static inline functions with static local variables

    Martin Wells, Oct 6, 2007, in forum: C Programming
    Replies:
    10
    Views:
    726
    Army1987
    Oct 8, 2007
  4. dolphin
    Replies:
    3
    Views:
    1,399
    Pete Becker
    Dec 5, 2007
  5. Replies:
    9
    Views:
    1,008
Loading...

Share This Page