tags:

views:

129

answers:

2

I keep running into this issue:

class CCreateShortcutTask : public CTask
{
public:
    CCreateShortcutTask(
     CFilename                         filename,  // shortcut to create (or overwrite)
     Toolbox::Windows::CShellLinkInfo  definition  // shortcut definition
    ) 
    ...

Having to spell out Toolbox::Windows::CShellLinkInfo seems highly questionable to me. This is in a header, so I surely don't wish to issue a using namespace declaration or I'll drag that namespace into every client file that includes this header.

But I don't seriously want to have to fully name these things in the class interface itself. I'd really love to be able to do something like:

class CCreateShortcutTask : public CTask
{
    using namespace Toolbox::Windows;
    -or possibly-
    using Toolbox::Windows::CShellLinkInfo;

public:
    CCreateShortcutTask(
     CFilename       filename,  // shortcut to create (or overwrite)
     CShellLinkInfo  definition  // shortcut definition
    ) 
    ...

But these seem to be illegal constructs.

Any ideas how to accomplish this?

EDIT: I have asked a broader version of this question here

+3  A: 

Maybe namespace alias will help you in some way. You could write the following:

namespace TW = Toolbox::Windows; // define short name

class CCreateShortcutTask : public CTask
{
public:
    CCreateShortcutTask(
        CFilename           filename,
        TW::CShellLinkInfo  definition
    )
Kirill V. Lyadvinsky
Thanks - I wasn't aware of such a thing. I guess that introduces another global name into any clients who #include my header, which isn't ideal. :(
Mordachai
Yes it does, if you look into the depths of Boost though you'll find they have used it: `namespace mpl_ = boost::mpl;`. Because of the trailing underscore, it's less likely to be used.
Matthieu M.
+6  A: 

I think there is a confusion on typedefs.

Using private typedefs is perfectly suitable (and often used). This relies on the fact that in C++ a typedef does not introduce a new type, but a synonym!

namespace VeryLongNamespaceYoullNeverWantToSeeAgain
{
  class SuchAStupidNameShouldBeBanned
  {
  public:
    typedef xxx iterator;
    typedef zzz value_type;

    static std::string Print(value_type);
  private:
  };

  void destroy(SuchAStupidNameShouldBeBanned&);
}

namespace short
{
  class MyStruct
  {
    typedef VeryLongNamespaceYoullNeverWantToSeeAgain::SuchAStupidNameShouldBeBanned Stupid;
  public:
    void destroyStupid()
    {
      Stupid::iterator it = m_stupid.begin(), end = m_stupid.end();

      std::cout << "Getting rid of ";
      for (; it != end; ++it) std::cout << Stupid::Print(*it) << " ";
      std::cout << std::endl;

      destroy(m_stupid);
    }

  private:
    Stupid m_stupid;
  };
}

Thus, private typedefs don't bother:

  • name lookup: destroy is correctly invoked
  • use of inner typedefs: iterator is found
  • use of static methods: Print is found

So you can really use them without many fuss. Furthermore they don't pollute the global space since they are inner to the class and though visible cannot be manipulated by the client directly so he does not rely on them.

Within the source file, you can use namespace aliasing and using directives (not using namespaces please) more liberally, so it's less of an issue.

Matthieu M.
Thanks - this helps clarify some things, and is extremely clearly written. :)
Mordachai
Although private typedefs are as good as it gets - I would prefer to see the ability to use scoped using declarations (or class scoped using namespace decls). Here's hoping that this will be better handled in the future.
Mordachai