0

This code does not compile:

class A;

void foo(A&) {
}

class A {
    void foo() {
        foo(*this); ///This does not compile
    }
};

Errors:

error: no matching function for call to 'A::foo(A&)'
         foo(*this);
                  ^
note: candidate is:
note: void A::foo()

This can be solved by calling ::foo(*this);


However, let's consider the case we are in a namespace:

namespace bar {

    class A;

    void foo(A&) {
    }

    class A {
        void foo() {
            foo(*this); ///This does not compile
        }
    };

}

Is there any other way than calling explicitly bar::foo(*this);? I mean, is there any way to look up names in the next surrounding declarative region, i.e. the containing bar namespace?

The use case is similar to what seen here.

Community
  • 1
  • 1
Antonio
  • 19,451
  • 13
  • 99
  • 197
  • 3
    There is a way: rename one of `foo`s to something else, this will also save you some sleepless nights. – Anton Savin Apr 14 '15 at 12:51
  • Your example is in no way related to this problem. The example is a case of polymorphism where this is a name look-up issue. – NathanOliver Apr 14 '15 at 12:59
  • @NathanOliver I corrected the pointer to the *accepted answer* to that question. – Antonio Apr 14 '15 at 13:00
  • And still my comment is the same. That solution is using polymorphism. – NathanOliver Apr 14 '15 at 13:02
  • 1
    While namespaces are similar to directories in filesystems, there's no equivalent to `../`. The closest you get is `*this` versus `./` – MSalters Apr 14 '15 at 13:03
  • There's no difference between `::foo` and `bar::foo`. `::foo` is just shorthand for something like `::foo`. – Dialecticus Apr 14 '15 at 13:06
  • @NathanOliver I *removed* polymorphism from my question, if you want you can add it by adding a `class B` identical to `class A` and adding a prototype of `foo` function taking class B as argument. I removed to single out my current "problem", as if I get an answer here, I can apply to the case seen there. See http://stackoverflow.com/help/mcve – Antonio Apr 14 '15 at 13:06
  • @MSalters Yep, I was thinking to the same example. And thanks for the edit! – Antonio Apr 14 '15 at 13:10
  • @Dialecticus I think in my second example `bar::foo` and `::foo` are different: The first is defined, the second not. – Antonio Apr 14 '15 at 13:19
  • In second example `::foo` is not defined for the same reason that some `::foo` would not be defined, which is that there is no function `foo` in global namespace. – Dialecticus Apr 14 '15 at 13:49

2 Answers2

4

I mean, is there any way to look up names in the next surrounding declarative region, i.e. the containing bar namespace?

No.

You can sort of do it the other way around:

void foo() {
    using bar::foo;
    foo(*this); /// OK now
}
Antonio
  • 19,451
  • 13
  • 99
  • 197
jrok
  • 54,456
  • 9
  • 109
  • 141
1

Not within the method itself. However, you can do this in the .cpp file:

namespace bar {
  namespace {
    auto outerFoo = foo;
  }
  void A::foo() {
      outerFoo(*this);
  }
}

Note that the name outerFoo is a hidden implementation detail which cannot cause name collisions (since it's in an anonymous namespace).

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • Great! I just regret not having access to C++11 `auto`, but in case I can get around it. Note: this becomes the accepted answer as it would work also when the `bar` namespace changes name. – Antonio Apr 14 '15 at 13:34
  • Well in that case you either have to spell out the type or write `inline void outerFoo(A& a) { foo(a); }`. – MSalters Apr 14 '15 at 13:40