Topic: Suggestion: private namespace


Author: Valentin.Bonnard@free.fr (Valentin Bonnard)
Date: Wed, 11 Apr 2001 20:14:11 GMT
Raw View
Christopher Eltschka  wrote:

> However, I think the following trick should give some
> protection even in the current language:

The following is from a header file, I guess:

> namespace X
> {
>   namespace // unnamed
>   {
[...]
>   }
>
>   void init()
>   {
>     priv::initHelper<int>::init();
>       // accesses X::(unnamed)::priv::initHelper<int>
>   }

You rarely want to use unnamed namespaces in header files
(do you declare static functions in headers   ?).

You never ever want to use members of unnamed namespaces
in a member of a unnamed namespace in a header file.

--

Valentin Bonnard

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Christopher Eltschka <celtschk@dollywood.itp.tuwien.ac.at>
Date: Thu, 12 Apr 2001 09:42:10 GMT
Raw View
Valentin Bonnard wrote:
>
> Christopher Eltschka  wrote:
>
> > However, I think the following trick should give some
> > protection even in the current language:
>
> The following is from a header file, I guess:

I didn't think about that; but of course, if it's not in a header file,
the trick doesn't make sense. And in header files, as you note, it
doesn't work. I should have thought more about it.

If you look at the code, you'll see that it is not written in a way
suitable for header files (even if not looking on the namespace
at all).

>
> > namespace X
> > {
> >   namespace // unnamed
> >   {
> [...]
> >   }
> >
> >   void init()
> >   {
> >     priv::initHelper<int>::init();
> >       // accesses X::(unnamed)::priv::initHelper<int>
> >   }
>
> You rarely want to use unnamed namespaces in header files
> (do you declare static functions in headers ?).
>
> You never ever want to use members of unnamed namespaces
> in a member of a unnamed namespace in a header file.

Also, you never want to define a non-inline non-template function
in a header file. ;-)

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Christopher Eltschka <celtschk@dollywood.itp.tuwien.ac.at>
Date: Mon, 9 Apr 2001 19:58:00 GMT
Raw View
Daniel Frey wrote:

[...]

> > namespaces aren't about accessibillity, so trying to control
> > access at this level is doomed to fail.
>
> Why? Let's think it a bit further. I'd like to modify my originally
> suggested syntax to match the class-style syntax better. A namespace
> could have sections like classes:
>
> namespace X
> {
> private:
>    template< typename T > class initHelper { ... };
>
> public:
>    void init()
>    {
>       initHelper< int >::init();
>       initHelper< long >::init();
>       initHelper< std::string >::init();
>    }
> }
>
> It should be equally hard to break this encapsulation as it is for
> classes.

Well, if you write this into a header file (which I cannot
modify), I can simply break your encapsulation by doing

#include "X.h"

// I want to access initHelper<double>:

namespace X // reopen your namespace
{
  typedef initHelper<double> doubleHelper;
    // I'm inside namespace X, so I may do it
}

void foo()
{
  X::doubleHelper::init(); // calls X::initHelper<double>::init()
}

The difference to class is that a class cannot be re-opened.
Therefore I cannot add something (like a typedef) to a class
defined by a header without changing that header. But I can
easily re-open a namespace and add whatever I like.

However, I think the following trick should give some
protection even in the current language:

namespace X
{
  namespace // unnamed
  {
    namespace priv
    {
      template<class T> class initHelper { ... };
    }
  }

  void init()
  {
    priv::initHelper<int>::init();
      // accesses X::(unnamed)::priv::initHelper<int>
  }

  namespace priv {} // hides (unnamed)::priv
}

void foo()
{
  X::priv::initHelper<double>::init();
    // Error: no initHelper<double> in X::priv
}

[...]

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Daniel Frey <daniel.frey@aixigo.de>
Date: Mon, 26 Mar 2001 16:45:26 GMT
Raw View
Valentin Bonnard wrote:
>=20
> It's very easy to bypass this ``encapsulation'':
>=20
> namespace Something {
>     typedef X spy_X;
>     namespace spy {
>         using Something::someFunction;
>     }
> }
> using namespace Something;

I should have been more specific. I meant to allow public/private for
namespaces as for classes. Even protected could be useful. When
something is declared inside the private part of a namespace it cannot
be used from the outside. Like a private function of a class, it is
simply not visible.

> You can now use spy_X or spy::someFunction anywhere (remember
> that, according to the philosophy of C++, encapsulation must
> be hard enough to break...).

What about this:

class X
{
private:
   class spy_Y { ... };

public:
   typedef spy_Y Y;
};

allows breaking (bypassing) the encapsulation for classes, if I follow
your argument above.

> namespaces aren't about accessibillity, so trying to control
> access at this level is doomed to fail.

Why? Let's think it a bit further. I'd like to modify my originally
suggested syntax to match the class-style syntax better. A namespace
could have sections like classes:

namespace X
{
private:
   template< typename T > class initHelper { ... };

public:
   void init()
   {
      initHelper< int >::init();
      initHelper< long >::init();
      initHelper< std::string >::init();
   }
}

It should be equally hard to break this encapsulation as it is for
classes. Why could we want something like that? Let's have a look at the
STL. It is implemented in a lot of header files, as a lot of things
cannot and should not be put into implementation files. But these
headers contain a lot of unprotected implementation-specific stuff.
Putting things in a namespace 'Detail' gives the user a hint, but it's
not really a good solution. It's like a class where all functions are
public, but some are named 'detail_myFunction',
'detail_anotherFunction', etc. Also, in my project we use 'Detail'
pretty often, so you might get conflicts inside your Detail-namespace.
This ends up in making the identifiers larger and less readable.
Therefore, I also suggest using protected for namespaces. While private
means that identifiers declared here can only be used inside this single
namespace block, protected allows using the classes, typedefs, etc. in
other blocks of the same namespace (as namespaces are open). Only public
allows access from the outside (and is the default for namespaces, so we
are 100% compatible). The use of 'protected' is different for namespaces
as classes are not 'open' and namespaces cannot be derived. Still I
think it's a useful thing, as no new keywords are introduced, no
existing code gets broken and its not too different from existing
concepts already present in the language.

Regards, Daniel

--
Daniel Frey

aixigo AG - financial training, research and technology
Schlo=DF-Rahe-Stra=DFe 15, 52072 Aachen, Germany
fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99
eMail: daniel.frey@aixigo.de, web: http://www.aixigo.de

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: qrczak@knm.org.pl (Marcin 'Qrczak' Kowalczyk)
Date: Mon, 26 Mar 2001 18:24:53 GMT
Raw View
Mon, 26 Mar 2001 16:45:26 GMT, Daniel Frey <daniel.frey@aixigo.de> pisze:

> When something is declared inside the private part of a namespace
> it cannot be used from the outside.

How do you define "outside"? Anybody can write

namespace Something
{
   =20
    and get inside the namespace!

> class X
> {
> private:
>    class spy_Y { ... };
>=20
> public:
>    typedef spy_Y Y;
> };
>=20
> allows breaking (bypassing) the encapsulation for classes,
> if I follow your argument above.

This usage of private is meaningless, because you reexport the private
thing under a different name.

But they are usages which are not meaningless. And classes cannot be
reopened like namespaces, so the restriction works.

--=20
 __("<  Marcin Kowalczyk * qrczak@knm.org.pl http://qrczak.ids.net.pl/
 \__/
  ^^                      SYGNATURA ZAST=CAPCZA
QRCZAK

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Daniel Frey <daniel.frey@aixigo.de>
Date: Fri, 23 Mar 2001 11:57:14 GMT
Raw View
Hi,

I often use something like this:

namespace Something
{
   namespace Detail
   {=20
      class X {...};
   }

   class Y { ... uses X ... };
}

Would it make sense to allow 'private namespace Detail' meaning that
this namespace can only be references from inside the namespace it was
declare in? This would help to prevent anyone from the outside to use
the content of the namespace. The same could apply to classes or
functions as well:

namespace Something
{
   private void someFunction() {...}
   private class X { ... uses someFunction(); ... };
   class Y { ... uses X ... };
}

// Can't access Something::X or Something::someFunction() here, just
Something::Y

IMHO this could allow even better encapsulation. Just an idea...

Regards, Daniel

--
Daniel Frey

aixigo AG - financial training, research and technology
Schlo=DF-Rahe-Stra=DFe 15, 52072 Aachen, Germany
fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99
eMail: daniel.frey@aixigo.de, web: http://www.aixigo.de

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Steve Clamage <stephen.clamage@sun.com>
Date: Fri, 23 Mar 2001 21:37:00 GMT
Raw View
Daniel Frey wrote:
>
> Hi,
>
> I often use something like this:
>
> namespace Something
> {
>    namespace Detail
>    {
>       class X {...};
>    }
>
>    class Y { ... uses X ... };
> }
>
> Would it make sense to allow 'private namespace Detail' meaning that
> this namespace can only be references from inside the namespace it was
> declare in? This would help to prevent anyone from the outside to use
> the content of the namespace.

You can close and reopen a namespace as many times as you like. Put the
public declarations in the header, and the parts you want to hide in the
implementation file.

--
Steve Clamage, stephen.clamage@sun.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Valentin.Bonnard@free.fr (Valentin Bonnard)
Date: Fri, 23 Mar 2001 21:39:53 GMT
Raw View
Daniel Frey  wrote:

> I often use something like this:
>
> namespace Something
> {
>    namespace Detail
>    {=20
>       class X {...};
>    }
>
>    class Y { ... uses X ... };
> }
>
> Would it make sense to allow 'private namespace Detail' meaning that
> this namespace can only be references from inside the namespace it was
> declare in? This would help to prevent anyone from the outside to use
> the content of the namespace. The same could apply to classes or
> functions as well:
>
> namespace Something
> {
>    private void someFunction() {...}
>    private class X { ... uses someFunction(); ... };
>    class Y { ... uses X ... };
> }
>
> // Can't access Something::X or Something::someFunction() here, just
> Something::Y
>
> IMHO this could allow even better encapsulation. Just an idea...

It's very easy to bypass this ``encapsulation'':

namespace Something {
    typedef X spy_X;
    namespace spy {
        using Something::someFunction;
    }
}
using namespace Something;

You can now use spy_X or spy::someFunction anywhere (remember
that, according to the philosophy of C++, encapsulation must
be hard enough to break...).

namespaces aren't about accessibillity, so trying to control
access at this level is doomed to fail.

--
Valentin Bonnard

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]