tags:

views:

204

answers:

4

I have some inline functions contained within a namespace in a header file and am not currently in a position to move them into a cpp file. Some of these inline functions use magic constants, for example:

// Foo.h
namespace Foo
{
    const int BAR = 1234;

    inline void someFunc()
    {
        // Do something with BAR
    }
}

However, I want to make these magic constants private - any ideas how? My first thought was to use an anonymous namespace thus:

// Foo.h
namespace Foo
{
    namespace
    {
        // 'private' constants here
        const int BAR = 1234;
    }

    inline void someFunc()
    {
        // Do something with BAR
    }
}

However, this doesn't work and Foo::BAR is available to any cpp file that includes Foo.h? Is there a way to do this without creating an implementation cpp file?

A: 

Namespaces don't have the concept of public and private, but classes do. Make your namespace a class.

anon
+4  A: 

You can't, anonymous namespaces work for the translation unit they are defined in (or included into in your case).
You could consider moving them into a detail namespace to signal to the user that they are internal details:

namespace foo {
    namespace detail {
        int magic = 42;
    }

    // ... use detail::magic
}
Georg Fritzsche
This is also the convention boost uses. It works well as long as you tell everyone the simple, "Never enter a detail namespace.", which most wouldn't do anyway.
GMan
+1  A: 

Put them in a special namespace or name them specially, combined with a project convention that such things are non-public:

namespace foo {
  namespace detail { // as in "implementation details"
    inline int answer() { return 42; }
    const int perfect = 28;
  }
  std::string _question(); // not part of foo's "public interface" by convention

  int this_is_public() {
    using namespace detail; // now don't have to prefix detail::
    return answer() + perfect + _question().length();
  }
}

Anyone using names documented as non-public will circumvent any "protection" you try; which highlights the real concern: documenting what's part of the public interface and may be relied upon.

Unnamed namespaces solve a different problem: getting names unique to a particular TU. They won't help here.

Roger Pate
+1  A: 

How about:

namespace Foo {
    class foo_detail {
    private:
        enum {
            BAR = 1234,
        };

        friend void someFunc();
    };

    inline
    void someFunc() {
        // something with foo_detail::BAR
    }
}

This makes the constant nonaccessible for anyone else than the functions you mark as friends. You can make the class nonconstructable by making the constructor private to make sure that noone does try to instanciate the class.

villintehaspam