Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How narrow should a using declaration be?

I have this little class widget that uses a std::string. It uses it in many places, often in conjunction to a std::vector. So you can see, that the typenames become very long and annoying.

I want to utilize the using keyword, i.e. using std::string;

The question is, where is the best place to place it?

// widget.h file
#ifndef WIDGET
#define WIDGET

// (1)
namespace example {
    // (2)

    namespace nested {
        // (3)

        class widget {  
        public:
            // (4)
            ...
        private:
            // (5)
            std::string name_;
            ...
        };

    }
}

#endif

My questions are:

  1. If I place it in (1) then everybody who includes widget.h will have their scope polluted with string?
  2. In places (2) and (3), it's the same story as in 1. only that the namespaces example and example::nested will be polluted in a second file that includes widget.h?
  3. In places (4) and (5), the declaration is quite isolated, but will it be visible in the implementation (Cpp) file and in inheriting classes?

Thanks in advance!

like image 204
Xlaudius Avatar asked Mar 07 '13 16:03

Xlaudius


1 Answers

Do not do it in (1).
Everybody will curse your name for a thousand years.
As a user of your class I don't mind you polluting your own namespace. But I will be upset if you pollute any of my namespaces (including global) as this will affect how my code is compiled. Why is "using namespace std" considered bad practice?

You can't use it at (4) or (5).

Since I (personally) would want to bind it as close as possible to the point of usage (to prevent pollution).
The best you can do is (3).

But I would not even do that. I am explicit about anything from standard. But I would typedef my container type.

private: //(so at 5) Don't need to expose internal details of your class.
    typedef std::vector<std::string>   MyCont;

This is a better technique as you will only need to make a change in one place and changes will cascade.

// Sub typedefs now will no longer need to change if you change
// The type of container. Just change the container typedef and
// now the iterators are automatically correct.
public: //(so at 4)  Iterators are public (and not exposing the implementation).
    typedef MyCont::iterator       iterator;
    typedef MyCont::const_iterator const_iterator;
like image 72
Martin York Avatar answered Sep 23 '22 11:09

Martin York