2

I'm dealing with a class that defines a friend function in the class without outside declaration

namespace our_namespace {
template <typename T>
struct our_container {

  friend our_container set_union(our_container const &, our_container const &) {
    // meaningless for the example here, just a valid definition
    // no valid semantics
    return our_container{};
  }
};
}  // namespace our_namespace

As discussed (e.g. here or here) the function set_union is not in the our_namespace namespace but will be found by argument dependent lookup:

auto foo(std::vector<our_namespace::our_container<float>> in) {
  // works:
  return set_union(in[0], in[1]);
}

I noticed however that in the debug flags set_union appears to be in the our_namespace namespace

        mov     rdi, qword ptr [rbp - 40] # 8-byte Reload
        mov     rsi, rax
        call    our_namespace::set_union(our_namespace::our_container<float> const&, our_namespace::our_container<float> const&)
        add     rsp, 48
        pop     rbp
        ret
our_namespace::set_union(our_namespace::our_container<float> const&, our_namespace::our_container<float> const&): # @our_namespace::set_union(our_namespace::our_container<float> const&, our_namespace::our_container<float> const&)
        push    rbp
        mov     rbp, rsp
        mov     qword ptr [rbp - 16], rdi
        mov     qword ptr [rbp - 24], rsi
        pop     rbp
        ret

although I can't call it as our_namespace::set_union

auto foo(std::vector<our_namespace::our_container<float>> in) {
  // fails:
  return our_namespace::set_union(in[0], in[1]);
}

Any hints about how the debug information is to be understood?

EDIT: The set_union function body is only a strawdog example here to have a valid definition.

pseyfert
  • 3,263
  • 3
  • 21
  • 47

1 Answers1

5

The C++ standard only defines compiler behavior in regards to the code compilation and behavior of the resulting program. It doesn't define all the aspects of code generation, and in particular, it doesn't define debug symbols.

So your compiler correctly (as per Standard) disallows calling the function through namespace it is not in. But since the function does exist and you should be able to debug it, it needs to put debug symbol somewhere. Enclosing namespace seems to be a reasonable choice.

SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • Hm, triggered by [this answer](https://stackoverflow.com/a/54580751), I looked at the intermediate compiler steps [here](https://godbolt.org/z/-ho6ka) and this looks like `set_union` is in the `our_namespace`. I'm confused. – pseyfert Feb 07 '19 at 19:46
  • 1
    @pseyfert do not confuse implementation detail with formal language rules. The rules are such that the name can't be found in the namespace (only through ADL lookup), so for all intents and purposes it is not in the namespace from the code point of view. The name exists, though, and compiler would need to generate the symbol and everything, and it puts the symbol in the namespace for codegeneration perspective. – SergeyA Feb 07 '19 at 19:50