Reputation: 1315
I'm trying to use an std::initializer_list as an argument in a function that uses argument-dependent lookup (ADL). But I don't get it to work and I don't understand why. The following is a minimal failing example:
#include <initializer_list>
#include <iostream>
class Foo {
public:
inline friend void bar(std::initializer_list<Foo> v) {
std::cout << "size = " << v.size() << std::endl;
}
};
void baz(std::initializer_list<Foo> v) {
std::cout << "size = " << v.size() << std::endl;
}
int main(){
Foo a;
//bar({a,a}); // error: use of undeclared identifier 'bar'
baz({a,a}); // works
return 0;
}
As seen above, an equivalent global function works just fine. Why does the above not work?
I'm using clang on OS X 10.10.
Upvotes: 4
Views: 213
Reputation: 208353
I believe that the problem is that the subexpression1 { a, a }
does not really have a type, and as such it does not have associated types or namespaces which in turn means that ADL does not kick in. If you have a function in the global namespace, normal lookup will find it, and it will find that { a, a }
can match the function call as the initializer for std::initializer_list<Foo>
.
1 The syntax { a, a }
is called braced-init-list and it is not really an expression (or subexpression) in the language.
Upvotes: 8
Reputation: 66922
When the compiler sees bar({a,a})
, it doesn't know the type of the arguments, so it searches for bar
in the global namespace (::
), and nowhere else. If you changed that line to Foo{a,a}
, then it knows the argument is a Foo
, and so also searches the Foo
class for functions.
Upvotes: 2