ADL in case of equal-named member function - c++

The situation is that some member function bar::Bar::frobnicate wants to utilize ADL to find a function from some unknown namespace, within a function that has an identical name. However, it only finds its own name.
Testcase
(Note that in reality, Bar is a Foo-agnostic template; this is just the reproducible, minimal testcase)
namespace foo {
struct Foo {};
void frobnicate(Foo const &) {}
}
namespace bar {
struct Bar {
void frobnicate() {
foo::Foo foo;
frobnicate(foo); // <-- error
}
};
}
int main () {
bar::Bar x;
x.frobnicate();
frobnicate(foo::Foo());
}
Results in:
test.cc: In member function ‘void bar::Bar::frobnicate()’:
test.cc:10:31: error: no matching function for call to ‘bar::Bar::frobnicate(foo::Foo&)’
test.cc:10:31: note: candidate is:
test.cc:8:18: note: void bar::Bar::frobnicate()
test.cc:8:18: note: candidate expects 0 arguments, 1 provided
Standard
I understand that this is correct compiler behaviour:
3.4.1 Unqualified name lookup [basic.lookup.unqual]
(...) name lookup ends as soon as a declaration is found for the name (...)
and only after unqualified lookup failed, argument dependent lookup comes into play:
3.4.2 Argument-dependent name lookup [basic.lookup.argdep]
When the postfix-expression in a function call (5.2.2) is an unqualified-id, other namespaces not considered
during the usual unqualified lookup (3.4.1) may be searched
Workaround
My current workaround is to introduce a special traits class that does not define the clashing name itself:
struct BarTraits {
void frobnicate_(foo::Foo const &b) {
frobnicate(b);
}
};
or this ligher version:
void frobnicate_(foo::Foo const &c) { frobnicate(c); }
Question
Are there better alternatives than introducing such traits classes?
Explicitly qualifying the call as foo::frobnicate(foo) is not an option here, because (as mentioned) the Bar class is a template upon Foo in reality and should not only work for types in the foo namespace.

As you found out yourself, adding a member function frobnicate to the class interface of Bar (or Bar<T> in the template case), will prevent ADL from finding foo::frobnicate.
The easiest -and in this case idiomatic- way to add frobnicate functionality to a class Bar (or to a class template Bar<T>) is to add a non-member function frobnicate(Bar) (or function template frobnicate(Bar<T>)) to the namespace bar
namespace foo {
struct Foo {};
void frobnicate(Foo const &) {}
}
namespace bar {
template<class T>
struct Bar {
T t;
};
template<class T>
void frobnicate(Bar<T> const& b)
{
frobnicate(b.t);
}
}
int main () {
bar::Bar<foo::Foo> x;
frobnicate(x);
frobnicate(foo::Foo());
}
If you insist on having a member function, you will have to rename it to something like do_frobnicate(). I would not use type traits tricks to get the same behavior as it is an indirect approach, and makes the class interfaces much harder to understand (remember Stroustrup's motto: "represent your ideas directly in code").

you can use this trick
namespace dummy { void your_func(may be some parameteres); }
struct bar {
void member() {
using dummy::your_func; // now your call will find that and ADL will kick in

I just do it with a proxy function
namespace utils
{
int lookup_adl(int arg)
{
return lookup(arg);// ADL search
}
struct Foo
{
int lookup(int arg) { return ::utils::lookup_adl(arg);}
};
}

Related

Do c++ inline friend functions cause name hiding between namespaces?

Consider the following code:
namespace Foo1 {
void add( int ) {}
void subtract( int ) {}
}
namespace Foo2 {
class Bar {
public:
friend void add( Bar ) {}
};
void subtract( Bar ) {}
void xxx() {
int i = 0;
using namespace Foo1;
add( i ); // Is this an error or not?
subtract( i ); // This is an error due to name hiding
}
}
In the Foo2::xxx() I used the using namespace to be able to access both Foo1::add and Foo1::subtract. The call to the subtract is obviously an error because the Foo2::subtract
hides the name. But the Foo2::add should not really be visible in Foo2 as it can only
be found using ADL and it should not hide the Foo1::add. Is my understanding correct?
I have tried the above code on multiple versions of MSVC and gcc. The former has consistently
rejected the add(i) call but error messages were not clear to me. The latter has consistently accepted it. Which of these (if any) is correct?
I think GCC is right here.
[namespace.memdef] (emphasis mine)
3 If a friend declaration in a non-local class first declares a
class, function, class template or function template the friend is a
member of the innermost enclosing namespace. The friend declaration
does not by itself make the name visible to unqualified lookup
([basic.lookup.unqual]) or qualified lookup ([basic.lookup.qual]).
[ Note: The name of the friend will be visible in its namespace if a
matching declaration is provided at namespace scope (either before or
after the class definition granting friendship).  — end note ] If a
friend function or function template is called, its name may be found
by the name lookup that considers functions from namespaces and
classes associated with the types of the function arguments
([basic.lookup.argdep]).
As such, the unqualified add( i ) should not by itself find the declaration of add( Bar ), which means lookup should continue and consider the names brought in by the using directive. And since the argument is not of a class type, ADL is out of the question. I'd conclude that add( Bar ) should not hide add( int ).
As already was pointed to (The C++ 20 Standard, 9.7.1.2 Namespace member definitions)
3 If a friend declaration in a non-local class first declares a class,
function, class template or function template100 the friend is a
member of the innermost enclosing namespace.
So this friend function add is a member of the namespace Foo2. However it is invisible in the namespace Foo2 until a corresponding function declaration appears in the namespace Foo2. And can be found only due to the argument-dependent look-up.
namespace Foo2 {
class Bar {
public:
friend void add( Bar ) {}
};
//..
The name add from the namespace Foo1 would be hidden if you write before the function xxx
namespace Foo2 {
class Bar {
public:
friend void add( Bar ) {}
};
void add( Bar );
//...
That is if the friend function add will be redeclared in the enclosing namespace.
Within the function xxx
void xxx() {
int i = 0;
using namespace Foo1;
add( i ); // Is this an error or not?
subtract( i ); // This is an error due to name hiding
}
the compiler considers the name substract in the following order. At first it looks through the enclosing namespace that is the namespace Foo2. And this namespace has the declared name substract. So the process of searching stops. The overloaded function void substract( int ) is not found because due to the using directive it is considered as a member of the global namespace. That is of the namespace that enclose the namespace specified in the using directive and the namespace that contains the using directive.
You can consider it the following way (due to the using directibe)
// the global namespace
void subtract( int ) {}
namespace Foo2
{
class Bar {
public:
friend void add( Bar ) {}
};
void subtract( Bar ) {}
void xxx() {
int i = 0;
// using namespace Foo1;
add( i ); // Is this an error or not?
subtract( i ); // This is an error due to name hiding
}
}
Instead of the using directive you could use a using declarations to make the both functions from the namespace Foo1 visible in the function xxx.
For example
void xxx() {
int i = 0;
using Foo1::subtract, Foo1::add;
add( i ); // Is this an error or not?
subtract( i ); // This is an error due to name hiding
}

Forcing name lookup to consider namespace scope

This question is somewhat related to point of instantiation and name binding but not exactly. The question is about the standard and how it resolve lookup of symbols inside template definitions.
Consider this example, loosely based on ostream library:
// Output module
class Output {
public:
void operator<<(int);
void operator<<(double);
...
};
// Item module
class Item {
friend void operator<<(Output& obj, const Item& x) {
...
}
};
// Main program
int main() {
Output out;
Item item;
out << 3;
out << 2.0;
out << item;
}
In this example, the key points is that the output module is defined before any modules that use it and there is one module (Item module) that uses the output module to emit items.
This allow the base emit operators to be defined inside the Output class, but any module that define new classes and want to provide an emit method can do so by providing a friend function with two arguments. All fine so far.
Now, let's try to use the same idea without operator overloading and instead use plan member functions for the pre-defined emit functions for the base type and still allow class-specific emit functions to be defined as friend functions for the class:
class Output {
public:
template <class Type>
void emit(Type x) {
emit(*this, x);
}
void emit(int);
void emit(double);
};
class Item {
friend void emit(Output& obj, const Item& x) {
...
}
...
};
int main() {
Output out;
Item item;
out.emit(3);
out.emit(2.0);
out.emit(item);
}
Compared to the previous code, there is a template function added because it should not be necessary to have different calling conventions depending on the type. In other words, it should be possible to use the convention out.emit(...) regardless of what item is being emitted.
However, when compiling this (using GCC 4.8.4), we get the following error:
example.cc: In instantiation of ‘void Output::emit(Type) [with Type = Item]’:
example.cc:49:20: required from here
example.cc:33:9: error: no matching function for call to ‘Output::emit(Output&, Item&)’
emit(*this, x);
^
example.cc:33:9: note: candidates are:
example.cc:32:12: note: template<class Type> void Output::emit(Type)
void emit(Type x) {
^
example.cc:32:12: note: template argument deduction/substitution failed:
example.cc:33:9: note: candidate expects 1 argument, 2 provided
emit(*this, x);
^
example.cc:36:12: note: void Output::emit(int)
void emit(int) {
^
example.cc:36:12: note: candidate expects 1 argument, 2 provided
example.cc:37:12: note: void Output::emit(double)
void emit(double) {
^
example.cc:37:12: note: candidate expects 1 argument, 2 provided
In other words, the top-level emit function is never considered and instead only the member functions inside Output class is considered when resolving the name.
I assumed this was because the symbol emit was not a dependent name and hence was looked up at the point of definition (of the template) instead of point of instantiation, but section 14.6.2 §1 in the C++ Standard says (slightly edited):
[...] In an expression of the form:
postfix-expression ( expression-list opt )
where the postfix-expression is an identifier the identifier denotes a dependent name if and only if any of the expressions in expression-list is a type-dependent expression (14.6.2.2).
And further, in 14.6.2.2 ("Type-dependent expressions") §2 it says:
this is type-dependent if the class type of the enclosing member function is dependent
Which, AIUI, is the case here.
So, the questions are:
Why doesn't the lookup consider the top-level version of emit in the name resolution here?
Is it possible to make the second example work in the same way as the first one so that the template member function definition will consider both member functions or namespace scope functions at the point of instantiation?
Update: Changed the title of the post to be more accurate and did a slight edit of the quotes from the standard.
As Johannes points out, if a member function is found ADL is not invoked and ADL is necessary to find the friend declaration of Item.
So, to answer the first question, Section 3.4.2 §2 in the C++ standard (C++03 version) says:
If the ordinary unqualified lookup of the name finds the declaration of a class member function, the associated namespaces and classes are not considered. [...]
To answer the second question, here is the fixed sample code:
namespace emitter {
class Output;
template <class Type>
void emit(Output& out, const Type& t) {
emit(out, t);
}
class Output {
public:
template <class Type>
void emit(Type x) {
using emitter::emit;
emit(*this, x);
}
void emit(int);
void emit(double);
};
}
class Item {
friend void emit(emitter::Output& obj, const Item& x) {
...
}
};
I am, however, still struggling to find the paragraph that clarifies why the using declaration solves the issue. The closest I can find right now is 7.3.3 §13:
For the purpose of overload resolution, the functions which are introduced by a using-declaration into a derived class will be treated as through they were members of the derived class.
But this refers to using B::f in a class D derived from B, so not a perfect match.

Within a class in a namespace, can I exit **just** the class namespace?

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.
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
}
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).

Clang does not find function instantiated after function definition in template context

I have been experimenting with code derived from the "C++ Seasoning" presentation by Sean Parent, and have boiled my problem down to the following code:
#include <memory>
struct container {
struct concept {
virtual ~concept() {}
virtual void foo_() = 0;
};
template <class T> struct model : concept {
model (T x) : data_(x) {}
void foo_() {
foo(data_); // Line 13
}
T data_;
};
template <class T>
container(T x) : self_(new model<T>(x)) {} // Line 20
std::unique_ptr<concept> self_;
friend void foo(container &c) { c.self_->foo_(); }
};
void foo(int i) // Line 27
{
}
int main()
{
int i = 5;
container c(i); // Line 34
foo(c);
}
The problem I have is that this code that compiles with g++, and yet not with Clang.
Clang gives me the following error messages:
prio.cpp:13:13: error: call to function 'foo' that is neither visible in the
template definition nor found by argument-dependent lookup
foo(data_);
^
prio.cpp:20:32: note: in instantiation of member function
'container::model<int>::foo_' requested here
container(T x) : self_(new model<T>(x)) {}
^
prio.cpp:34:15: note: in instantiation of function template specialization
'container::container<int>' requested here
container c(i);
^
prio.cpp:27:6: note: 'foo' should be declared prior to the call site
void foo(int i)
^
My understanding is that overload resolution during templates occurs at the point of instantiation. In this case, that is line 34 (as marked above.) At this point, the global "foo" function is known. And yet, it appears not to resolve.
Note for posterity: This was with Clang built from trunk on 14/Jan/14
Is this a bug in Clang then, or with g++?
Gcc is wrong in this case, the code should not compile; but this is completely unrelated to the template. Friend declarations are particular in that they provide a declaration for a namespace level entity, but the declaration is not visible for normal lookup until a namespace declaration is also seen by the compiler.
Consider the simplified example:
struct X {
friend void f(int); // [1]
void g() { f(1); } // [2]
};
void h() { f(1); } // [3]
void f(int); // [4]
void i() { f(1); } // [5]
The friend declaration [1] inside the X class provides a declaration for a namespace level function f taking an int, but that declaration is not visible at namespace level until a namespace level declaration is present in [4]. Both [2] and [3] will fail to compile, although [5] will compile since at that point the compiler will have parsed the function declaration.
So how can the declaration in [1] be used by the compiler to resolve a call? In this particular case never. The friend declaration can only be found by argument dependent lookup, but ADL will only look inside X if one of the arguments to the function call is of type X. In this case, the function does not have any argument X, so lookup will never use the friend declaration for anything other than lifting the restrictions of access to the variables of X.
That is:
struct Y {
friend void f(int) {}
};
Without a latter namespace level declaration for f will declare and define a function that cannot be used anywhere in your program (lookup won't ever find it).
The simple workaround for your problem is to provide a declaration for the function at namespace level before the definition of the class:
#include <memory>
void foo(int);
struct container { // ...

What is going on here?

This doesn't compile,
#include <boost/intrusive_ptr.hpp>
class X
{
public:
void intrusive_ptr_add_ref(X* blah)
{
}
void intrusive_ptr_release(X * blah)
{
}
};
int main()
{
boost::intrusive_ptr<X> ex(new X);
}
But this does :
#include <boost/intrusive_ptr.hpp>
class X
{
public:
friend void intrusive_ptr_add_ref(X* blah)
{
}
friend void intrusive_ptr_release(X * blah)
{
}
};
int main()
{
boost::intrusive_ptr<X> ex(new X);
}
and this :
#include <boost/intrusive_ptr.hpp>
class X
{
public:
};
void intrusive_ptr_add_ref(X* blah)
{
}
void intrusive_ptr_release(X * blah)
{
}
int main()
{
boost::intrusive_ptr<X> ex(new X);
}
I suppose it has something to do with SFINAE (which I haven't as of yet bothered to understand) ? Does the friend qualifier put the defined function as a free function in the enclosed namespace ?
edit
Whoever removed their post, member functions non-friend as add_ref and release (these specific member functions are not mentioned in the documention...) did solve the problem. What happens with the nested definition with the friend qualifier ?
From the documentation of boost::intrusive_ptr:
Every new intrusive_ptr instance increments the reference count by using an unqualified call to the function intrusive_ptr_add_ref, passing it the pointer as an argument. Similarly, when an intrusive_ptr is destroyed, it calls intrusive_ptr_release; this function is responsible for destroying the object when its reference count drops to zero. The user is expected to provide suitable definitions of these two functions. On compilers that support argument-dependent lookup, intrusive_ptr_add_ref and intrusive_ptr_release should be defined in the namespace that corresponds to their parameter; otherwise, the definitions need to go in namespace boost.
This means that intrusive_ptr_add_ref and intrusive_ptr_release should not be member functions, but free functions (friend functions behave as such). Furthermore they are called without qualification, so they should be in the global namespace or somewhere found by ADL.
Edit: To your question about nested definitions with friend qualifier:
friend functions are defined as non memberfunctions, so friend void intrusive_ptr_add_ref(X* blah) will be called as intrusive_ptr_add_ref(my_x_ptr) instead of as my_x_ptr->intrusive_ptr_add_ref().