1

Assume I've code like this:

namespace foo {
  enum bar
  {
    fooBarA,
    fooBarB
  };
}

struct baz
{
  // TODO: map "bar" in this struct to make valid:
  bar returnSomething() { return fooBarA; }
};

// and also this:
void doSomething()
{
  baz myBaz;

  if( baz::fooBarA == myBaz.returnSomething() )
  { /* ... */ }
}

What kind of code could I put at the TODO section to make the rest valid? Some using or typedef?

PS: To avoid questions about the "why": The namespace is living in it's own header file and might be used by a few different classes that should agree on the values of fooBarA and fooBarB but also hide that they are based on foo as that's irrelevant for the guys using baz.

PPS: C++11 is allowed. Would enum class help?

PPPS: Other questions like using declaration with enum? handle the case where the enum is in a class and not directly in a namespace.

Community
  • 1
  • 1
Chris
  • 3,265
  • 5
  • 37
  • 50
  • Yes, `foo::bar` would work - but it wouldn't let me hide the fact that `bar` is not a "member" of `baz` to the user of `baz`. Or in other words, I'd like `bar` to look like a full member of `baz`. – Chris Sep 16 '12 at 11:41

2 Answers2

1

This way requires a small amount of work in foo namespace. But it should be transparent to existing user of foo::bar. Just enclose your foo::bar's values in some struct from which derive your baz class:

namespace foo {
  struct barValues
  {
    enum Values {
      fooBarA,
      fooBarB
   };
  };

  typedef barValues::Values bar;
  static const bar fooBarA = barValues::fooBarA;
  static const bar fooBarB = barValues::fooBarB;
}

struct baz : foo::barValues
{
  typedef foo::bar bar;
  bar returnSomething() { return fooBarA; }
};

// and also this:
void doSomething()
{
  baz myBaz;

  if( baz::fooBarA == myBaz.returnSomething() )
  { /* ... */ }
  if( foo::fooBarA == myBaz.returnSomething() )
  { /* ... */ }
}

Its advantage over other answer is that you enclose your foo::bar values in namespace foo - only there you add/modify/delete this enum values. This is safer I believe. Its disadvantage in comparison to other answer is that you have to modify other file which can't be an option.

PiotrNycz
  • 23,099
  • 7
  • 66
  • 112
  • Not the nice solution I hoped for but probably the best that's possible. – Chris Sep 17 '12 at 19:04
  • I was thinking about this - but could not find anything better. Maybe, if start with this syntax: `namespace foo { struct bar { enum Values { A, B }; }; }` then using as `foo::bar::A` everywhere - but for `baz` used as `baz::A`. Not sure if smarter but did not require to retype all names twice. – PiotrNycz Sep 17 '12 at 19:11
0

This would work

struct baz
{
    typedef foo::bar   bar;
    static const bar fooBarA = foo::fooBarA;
    static const bar fooBarB = foo::fooBarB;

  // This is now valid
  bar returnSomething() { return fooBarA; }
};

but I don't know if it is really useful. If your users try to overload some functions or something, they might be in for a surprise.

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
  • What is worse a maintainability hole is introduced. When someone modifies foo::bar - the baz must be changed too. Compiler will tell us about reducing or changing elements of foo::bar, but it will not say a word about extending foo::bar. – PiotrNycz Sep 16 '12 at 12:12
  • That would work but isn't quite useable. Imagine `bar` doesn't have two values but perhaps 100 different colors. Then every class using that enum would need additional 100 lines defining the values... – Chris Sep 16 '12 at 12:28
  • 1
    @Chris - Right, it is not very useful. On the other hand I don't know of any way to "import" enum values without mentioning each value separately. They are individual values, and not a package. – Bo Persson Sep 16 '12 at 12:31