#include within namespace scope

Discussion in 'C++' started by joecook@gmail.com, Feb 16, 2009.

  1. Guest

    Is there anything that prevents putting #include directives inside
    namespace scope within the standard?

    Let's say I have a (evil) header:

    header.h
    #include <vector>
    using namespace std; // bad doggy

    class Doo
    {
    public:
    vector<int> d;
    };
    ----------
    and a test.cc:
    namespace evil
    {
    #include "header.h"
    }
    int main()
    {
    // Nothing
    }

    gcc throws up all over the place. What rule am I violating?

    Joe C
    , Feb 16, 2009
    #1
    1. Advertising

  2. writes:

    > Is there anything that prevents putting #include directives inside
    > namespace scope within the standard?


    Nothing, but you will declare the stuff defined in the header inside
    this namespace.

    > Let's say I have a (evil) header:


    Therefore you have:


    namespace evil
    {
    #include <vector>
    using namespace std; // bad doggy

    class Doo
    {
    public:
    vector<int> d;
    };
    }
    int main()
    {
    // Nothing
    }

    That is, you are using a class evil::std::vector<int>
    Where is the implementation of this class?
    Notice that libg++ only defines methods such as std::vector<int>::clear,
    not evil::std::vector<int>::clear.

    So as long as you defined all the methods and classes you have defined
    in evil::std somewhere, and would link them with your program it would
    be ok.

    --
    __Pascal Bourguignon__
    Pascal J. Bourguignon, Feb 16, 2009
    #2
    1. Advertising

  3. Zeppe Guest

    wrote [16/02/09 13:27]:
    > Is there anything that prevents putting #include directives inside
    > namespace scope within the standard?


    I'd be surprised if it weren't.

    >
    > Let's say I have a (evil) header:
    >
    > header.h
    > #include <vector>


    [...]

    > and a test.cc:
    > namespace evil
    > {
    > #include "header.h"
    > }


    [...]

    > gcc throws up all over the place. What rule am I violating?


    The rule of common sense. The headers include a bounch of declarations
    and definitions within the namespace std, you cannot change the
    namespace and expect that everything works.

    A workaround is to #include <vector> in test.cc or elsewhere before the
    inclusion in header.h, so that the standard things stay the same. Sort
    of a new wrapper file:

    header_wrap.h

    #include <vector>
    namespace evil{
    #include <header.h> // vector won't be included in namespace evil.
    }

    Best wishes,

    Zeppe
    Zeppe, Feb 16, 2009
    #3
  4. Guest

    On Feb 16, 9:10 am, (Pascal J. Bourguignon)
    wrote:
    > writes:
    > > Is there anything that prevents putting #include directives inside
    > > namespace scope within the standard?

    >
    > Nothing, but you will declare the stuff defined in the header inside
    > this namespace.
    >
    > > Let's say I have a (evil) header:

    >
    > Therefore you have:
    >
    >     namespace evil
    >     {
    >     #include <vector>
    >     using namespace std;  // bad doggy
    >
    >     class Doo
    >     {
    >     public:
    >      vector<int> d;
    >     };
    >     }
    >     int main()
    >     {
    >       // Nothing
    >     }
    >
    > That is, you are using a class  evil::std::vector<int>
    > Where is the implementation of this class?
    > Notice that libg++ only defines methods such as std::vector<int>::clear,
    > not evil::std::vector<int>::clear.


    I expected the preprocessor to expand the include header at the
    location I have put it.
    I further expected that the compiler should always refer to ::std::
    instead of std::, and therefore 'std' will not get caught inside the
    namespace where it is not intended. Somewhere that expectation is
    being broken, and I'm still not sure exactly where..
    Joe C
    , Feb 16, 2009
    #4
  5. Guest

    On Feb 16, 10:18 am, wrote:
    > On Feb 16, 9:10 am, (Pascal J. Bourguignon)
    > wrote:
    >
    >
    >
    >
    >
    > > writes:
    > > > Is there anything that prevents putting #include directives inside
    > > > namespace scope within the standard?

    >
    > > Nothing, but you will declare the stuff defined in the header inside
    > > this namespace.

    >
    > > > Let's say I have a (evil) header:

    >
    > > Therefore you have:

    >
    > >     namespace evil
    > >     {
    > >     #include <vector>
    > >     using namespace std;  // bad doggy

    >
    > >     class Doo
    > >     {
    > >     public:
    > >      vector<int> d;
    > >     };
    > >     }
    > >     int main()
    > >     {
    > >       // Nothing
    > >     }

    >
    > > That is, you are using a class  evil::std::vector<int>
    > > Where is the implementation of this class?
    > > Notice that libg++ only defines methods such as std::vector<int>::clear,
    > > not evil::std::vector<int>::clear.

    >
    > I expected the preprocessor to expand the include header at the
    > location I have put it.
    > I further expected that the compiler should always refer to ::std::
    > instead of std::, and therefore 'std' will not get caught inside the
    > namespace where it is not intended.  Somewhere that expectation is
    > being broken, and I'm still not sure exactly where..
    > Joe C- Hide quoted text -
    >
    > - Show quoted text -


    To clarify,

    The standard states, "Whenever a name x defined in the standard
    library is mentioned, the name x is assumed to be fully qualified
    as ::std::x, unless explicitly described otherwise. For example, if
    the Effects section for library function F is described as calling
    library function G, the function ::std::G is meant."

    In this case, the compiler seems to be making the assumption that
    include directives will always be at global scope, but I cannot find
    any part of the standard that would back up such an assumption. That
    is what I am searching for.

    Thanks!
    Joe C
    , Feb 16, 2009
    #5
  6. writes:
    >> I expected the preprocessor to expand the include header at the
    >> location I have put it.


    That's what it does.

    >> I further expected that the compiler should always refer to ::std::
    >> instead of std::, and therefore 'std' will not get caught inside the
    >> namespace where it is not intended.


    They would have to write ::std:: all over the standard headers.

    >> Somewhere that expectation is
    >> being broken, and I'm still not sure exactly where..

    >
    > To clarify,
    >
    > The standard states, "Whenever a name x defined in the standard
    > library is mentioned, the name x is assumed to be fully qualified
    > as ::std::x, unless explicitly described otherwise. For example, if
    > the Effects section for library function F is described as calling
    > library function G, the function ::std::G is meant."


    This seems to me to be a meta-rule about the interpretation of the
    text of the standard. It says nothing about the header files.


    > In this case, the compiler seems to be making the assumption that
    > include directives will always be at global scope, but I cannot find
    > any part of the standard that would back up such an assumption. That
    > is what I am searching for.


    Or to infirm it. It would be nice to find it.

    --
    __Pascal Bourguignon__
    Pascal J. Bourguignon, Feb 16, 2009
    #6
  7. Zeppe Guest

    Victor Bazarov wrote [16/02/09 15:01]:
    > Zeppe wrote:
    >> wrote [16/02/09 13:27]:
    >>> Is there anything that prevents putting #include directives inside
    >>> namespace scope within the standard?

    >>
    >> I'd be surprised if it weren't.

    >
    > The concept of a namespace has nothing to do with the preprocessor. So,
    > those two are orthogonal, and there can be NO provision making the two
    > somehow connected. Are you surprised?


    In order for the std headers to work, they have to be included outside
    of any namespace. Whatever the reason, this is a rule, and I expect it
    to appear somewhere in the standard, since, as you said, namespaces and
    preprocessor are orthogonal and in principle I could expect to be able
    to include standard headers at any point.

    But, no, I'm not surprised, because of 17.4.2.1#3:
    "A translation unit shall include a header only outside of any external
    declaration or definition, and shall include the header lexically before
    the first reference to any of the entities it declares or first defines
    in that translation unit."

    >> The rule of common sense. The headers include a bounch of declarations
    >> and definitions within the namespace std,

    >
    > Actually, more precisely, the namespace ::std.


    yes, that is, of course. It was the whole core of the topic :)

    Best wishes,

    Zeppe
    Zeppe, Feb 16, 2009
    #7
  8. James Kanze Guest

    On Feb 16, 2:27 pm, wrote:
    > Is there anything that prevents putting #include directives
    > inside namespace scope within the standard?


    Of course not. Include happens before namespaces are
    recognized, and is pure textual inclusion. You can put one in
    the middle of a function, if that's what you want.
    The only restriction in the standard is with regards to the
    standard includes; these must be included "outside of any
    external declaration or definition." I'm not sure why the
    particular exact wording, but namespaces and classes do count as
    declarations, so the include of a standard header must be
    outside of them.

    > Let's say I have a (evil) header:


    > header.h
    > #include <vector>
    > using namespace std; // bad doggy


    > class Doo
    > {
    > public:
    > vector<int> d;};


    > ----------
    > and a test.cc:
    > namespace evil
    > {
    > #include "header.h"
    > }


    > int main()
    > {
    > // Nothing
    > }


    > gcc throws up all over the place. What rule am I violating?


    You're including a standard header (indirectly) inside a
    namespace.

    More generally, since headers are textual inclusion, it's very
    hard to write one which can really be included within a
    namespace. The standard doesn't care, but there's a very large
    possibility that the results will not be what you want (unless
    the header only contains #define).

    --
    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, Feb 17, 2009
    #8
  9. James Kanze Guest

    On Feb 16, 4:18 pm, wrote:
    > On Feb 16, 9:10 am, (Pascal J. Bourguignon)
    > wrote:
    > > writes:
    > > > Is there anything that prevents putting #include
    > > > directives inside namespace scope within the standard?


    > > Nothing, but you will declare the stuff defined in the
    > > header inside this namespace.


    > > > Let's say I have a (evil) header:


    > > Therefore you have:


    > > namespace evil
    > > {
    > > #include <vector>
    > > using namespace std; // bad doggy


    > > class Doo
    > > {
    > > public:
    > > vector<int> d;
    > > };
    > > }
    > > int main()
    > > {
    > > // Nothing
    > > }


    > > That is, you are using a class evil::std::vector<int>
    > > Where is the implementation of this class?
    > > Notice that libg++ only defines methods such as std::vector<int>::clear,
    > > not evil::std::vector<int>::clear.


    > I expected the preprocessor to expand the include header at
    > the location I have put it. I further expected that the
    > compiler should always refer to ::std:: instead of std::, and
    > therefore 'std' will not get caught inside the namespace where
    > it is not intended.


    Part of the problem may be that the library is doing just that:
    using ::std::, instead of just std::. So <vector> includes
    something like:

    namespace std
    {
    namespace _Private_ {
    class _UsedByVector { /* ... */ } ;
    }
    template< ... >
    class vector
    {
    // ...
    ::std::_Private_::_UsedByVector ...
    } ;
    }

    When you wrap this in namespace evil,
    ::std::_Private_::_UsedByVector isn't defined, only
    ::evil::std::_Private_::_UsedByVector.

    It's because of such things that the standard makes the
    requirement that standard headers may not be included in
    declarations or definitions.

    --
    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, Feb 17, 2009
    #9
  10. James Kanze Guest

    On Feb 16, 4:47 pm, wrote:
    > On Feb 16, 10:18 am, wrote:
    > > On Feb 16, 9:10 am, (Pascal J. Bourguignon)
    > > wrote:


    > > > writes:
    > > > > Is there anything that prevents putting #include
    > > > > directives inside namespace scope within the standard?


    > > > Nothing, but you will declare the stuff defined in the
    > > > header inside this namespace.


    > > > > Let's say I have a (evil) header:


    > > > Therefore you have:


    > > > namespace evil
    > > > {
    > > > #include <vector>
    > > > using namespace std; // bad doggy


    > > > class Doo
    > > > {
    > > > public:
    > > > vector<int> d;
    > > > };
    > > > }
    > > > int main()
    > > > {
    > > > // Nothing
    > > > }


    > > > That is, you are using a class evil::std::vector<int>
    > > > Where is the implementation of this class? Notice that
    > > > libg++ only defines methods such as
    > > > std::vector<int>::clear, not
    > > > evil::std::vector<int>::clear.


    > > I expected the preprocessor to expand the include header at
    > > the location I have put it. I further expected that the
    > > compiler should always refer to ::std:: instead of std::,
    > > and therefore 'std' will not get caught inside the namespace
    > > where it is not intended. Somewhere that expectation is
    > > being broken, and I'm still not sure exactly where..


    > To clarify,


    > The standard states, "Whenever a name x defined in the standard
    > library is mentioned, the name x is assumed to be fully qualified
    > as ::std::x, unless explicitly described otherwise. For example, if
    > the Effects section for library function F is described as calling
    > library function G, the function ::std::G is meant."


    I'm not sure where it says that, so I can't verify the context,
    but I imagine that it is talking about the use of names in user
    code. That the guarantees concerning e.g. vector only hold if
    vector actually refers to ::std::vector (and not for
    ::evil::std::vector). And of course, you can't define a class:

    template< ... >
    class ::std::vector ...

    (See §3.4.4/3, which specifies look-up after a class specifier
    or an enum specifier. Particularly "If the name is a
    qualified-id [the case in the above], [...]. If the name lookup
    does not find a previously declared class-name or enum-name, the
    elaborated-type-specifier is ill formed. In everyday terms:
    class ::std::whatever ...
    is ill formed unless there is a preceding
    namespace std { class whatever; }
    somewhere in global namespace.)

    > In this case, the compiler seems to be making the assumption
    > that include directives will always be at global scope, but I
    > cannot find any part of the standard that would back up such
    > an assumption.


    The "compiler" is making no assumptions what so ever. It is
    compiling what it sees, after textual inclusion. You're
    violating §17.4.2.1/3 "A translation unit shall include a header
    only outside of any external declaration, [...]"

    More generally, most people assume that headers will be included
    only outside of any external declaration when they write them.
    This is almost always a constraint on the use of a header
    (non-standard headers as well), and I suspect that it's often
    not documented---unless the library documents that you can
    include a header in a namespace, class definition or function
    definition, I would assume that you couldn't.

    --
    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, Feb 17, 2009
    #10
  11. James Kanze Guest

    On Feb 16, 5:06 pm, (Pascal J. Bourguignon)
    wrote:
    > writes:
    > >> I expected the preprocessor to expand the include header at
    > >> the location I have put it.


    > That's what it does.


    > >> I further expected that the compiler should always refer to
    > >> ::std:: instead of std::, and therefore 'std' will not get
    > >> caught inside the namespace where it is not intended.


    > They would have to write ::std:: all over the standard
    > headers.


    That doesn't help. You can't use a qualified name in an
    "elaborated type specifier" (something beginning with the key
    words "class", "struct", "union" or "enum") unless it has been
    previously declared. Which means the the first mention of the
    type cannot have the ::std::.

    > >> Somewhere that expectation is being broken, and I'm still
    > >> not sure exactly where..


    > > To clarify,


    > > The standard states, "Whenever a name x defined in the
    > > standard library is mentioned, the name x is assumed to be
    > > fully qualified as ::std::x, unless explicitly described
    > > otherwise. For example, if the Effects section for library
    > > function F is described as calling library function G, the
    > > function ::std::G is meant."


    > This seems to me to be a meta-rule about the interpretation of
    > the text of the standard. It says nothing about the header
    > files.


    It would have been nice if he'd have provided the reference, so
    we could see the context. I suspect what the above is saying is
    that when the standard defines the behavior, etc. of vector, it
    means ::std::vector. But it's hard to say without knowing the
    context where the statement was made.

    > > In this case, the compiler seems to be making the assumption
    > > that include directives will always be at global scope, but
    > > I cannot find any part of the standard that would back up
    > > such an assumption. That is what I am searching for.


    > Or to infirm it. It would be nice to find it.


    There are two separate issues.

    There is absolutely no requirement that an include must be at
    global scope. In the past, I've even used #include in a
    function body. (I find this bad practice, and today, I do not
    do it. Even if the include file is machine generated code,
    designed to be included in one, and only one location, I will
    ensure that the generated code will open and close any
    namespaces, classes or functions that it needs, and will include
    it at global scope.)

    There is a requirement that the standard headers be included
    outside any definition or declaration, i.e. outside of any
    namespace, class, enum, function or template. See §17.4.2.1.
    But this only applies to standard headers.

    Finally, it's worth remembering that most library authors
    probably make the same requirements, even if they don't say so.
    I can't find anything in Posix saying that you can't include its
    headers in the middle of a struct or function (since Posix is C,
    there's no issue of namespaces), but I wouldn't expect it to
    work. A priori, I would assume that any library have the same
    restrictions as the standard library with regards to using its
    headers, unless it explicitly documented them otherwise. In
    other words, unless there is contrary documentation:

    1. the headers may be included in any order;
    2. they may be included more than once, with no differing
    effect than if they were included only once,
    3. they must be included outside any other definition or
    declaration (at global scope, if you prefer, but also
    outside of any declaration or definition which doesn't
    introduce a new scope, e.g. enum); and
    4. they must be included before the first use of anything they
    define.

    There will usually also be requirements concerning names that
    may or may not be defined; something like:
    #define std 3.14159
    #include <vector>
    is forbidden by the standard, and I expect just about every
    library in existance has similar restrictions. (It might not
    care about std, but it will have other symbols which will cause
    problems.)

    --
    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, Feb 17, 2009
    #11
  12. Guest

    On Feb 17, 5:10 am, James Kanze <> wrote:

    > There is a requirement that the standard headers be included
    > outside any definition or declaration, i.e. outside of any
    > namespace, class, enum, function or template.  See §17.4.2.1.
    > But this only applies to standard headers.


    Appreciate all the comments, and thanks for finding the reference I
    was unable to find.
    Joe
    , Feb 17, 2009
    #12
    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. Paul Opal
    Replies:
    12
    Views:
    927
    Paul Opal
    Oct 11, 2004
  2. Anonymous
    Replies:
    3
    Views:
    513
    Ron Natalie
    Aug 18, 2003
  3. mark4asp
    Replies:
    2
    Views:
    2,194
    Harry Haller
    Nov 7, 2006
  4. Steven T. Hatton
    Replies:
    9
    Views:
    458
  5. Andreas Bogenberger
    Replies:
    3
    Views:
    881
    Andreas Bogenberger
    Feb 22, 2008
Loading...

Share This Page