Ambiguity between function inside unnamed namespace, and function outside
Asked Answered
D

6

20

Consider the following snippet:

void Foo() // 1
{
}

namespace
{
  void Foo() // 2
  {
  }
}

int main()
{
  Foo(); // Ambiguous.
  ::Foo(); // Calls the Foo in the global namespace (Foo #1).

  // I'm trying to call the `Foo` that's defined in the anonymous namespace (Foo #2).
}

How can I refer to something inside an anonymous namespace in this case?

Diffusive answered 9/9, 2010 at 2:21 Comment(0)
F
20

You can't. The standard contains the following section (§7.3.1.1, C++03):

An unnamed-namespace-definition behaves as if it were replaced by

  namespace unique { /* empty body */ }
  using namespace unique;
  namespace unique { namespace-body }

where all occurrences of unique in a translation unit are replaced by the same identifier and this identifier differs from all other identifiers in the entire program.

Thus you have no way to refer to that unique name.

You could however technically use something like the following instead:

int i;

namespace helper {
    namespace {
        int i;
        int j;
    }
}

using namespace helper;

void f() { 
    j++; // works
    i++; // still ambigous
    ::i++; // access to global namespace
    helper::i++; // access to unnamed namespace        
}
Frieda answered 9/9, 2010 at 2:27 Comment(6)
Okay, what the standard says makes sense. However, why is there an ambiguity, then? If I can't access the Foo in the anonymous namespace, the compiler should be able to deduce that the only other Foo is the one in global scope. I shouldn't have to use the scope resolution operator at all. Any thoughts on that aspect of the problem?Diffusive
Re: your edit -- That's pretty much what I'm doing now, except I use a wrapper function to get to the actual target function.Diffusive
@sharp: There are two symbols Foo in that scope. Consider an equivalent situation: namespace A { int i; } namespace B { int i; } using namespace A; using namespace B;.Frieda
Good point, but that still seems kind of ugly from the language perspective. =\Diffusive
@sharp: Ugly is having two functions with the same name like that. :)Galactopoietic
@GMan: Nah, this is ugly ;)Frieda
G
5

While Georg gives standard-complient, correct, right, and respectable answer, I'd like to offer my hacky one - use another namespace within the anonymous namespace:

#include <iostream>

using namespace std;

namespace
{
namespace inner
{
    int cout = 42;
}
}

int main()
{
    cout << inner::cout << endl;
    return 0;
}
Griff answered 9/9, 2010 at 2:36 Comment(0)
L
2

The only solution I can think of that doesn't modify the existing namespace arrangement is to delegate main to a function in the anonymous namespace. (main itself is required to be a global function (§3.6.1/1), so it cannot be in an anonymous namespace.)

void Foo() // 1
{
}

namespace
{
  void Foo() // 2
  {
  }
}

namespace { // re-open same anonymous namespace

    int do_main()
    {
      Foo(); // Calls local, anonymous namespace (Foo #2).
      ::Foo(); // Calls the Foo in the global namespace (Foo #1).

      return 0; // return not optional
    }

}

int main() {
    return do_main();
}
Luxor answered 9/9, 2010 at 2:37 Comment(0)
O
0

The only real way is to put the code you want to access that namespace within the namespace itself. There's no way to resolve to the unnamed namespace otherwise, since it has no identifier you can give it to solve the ambiguous resolution problem.

If your code is inside the namespace{} block itself, the local name gets priority over the global one, so a Foo() will call the Foo() within your namespace, and a ::Foo() will call the namespace at global scope.

Orthodoxy answered 9/9, 2010 at 2:32 Comment(0)
C
0

Just rename the local namespace function.

Cailly answered 27/11, 2013 at 15:57 Comment(0)
T
0
void Foo() // 1
{
}

namespace
{
  void Foo() // 2
  {
  }

  namespace detail
  {
    using Func = Foo;
  }
}

int main()
{
  Foo(); // Ambiguous.
  ::Foo(); // Calls the Foo in the global namespace (Foo #1).

  using Foo = detail::Func;
  Foo(); // Calls Foo #2.
}
Tipperary answered 23/1 at 7:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.