The problem relates to functoid objects ("function like" objects, ie ones with an operator() defined) and references to them within a namespace. When Koenig lookup is used to find such a reference-to-functoid, g++ seems to find it okay, but then states "cannot be used as a function". If I use an actual functoid object instead of a reference to one, it works fine. Here is an example: #include <iostream> namespace dummyx { struct Dummy { Dummy() {} }; struct DummyFunct { int operator()(Dummy d) const {return 5;} static DummyFunct& full() {static DummyFunct f; return f;} }; static DummyFunct& dummyFunct=DummyFunct::full(); DummyFunct myDummyFunct; DummyFunct& mymyDummyFunct=myDummyFunct; } int main() { ::dummyx::Dummy const d; std::cout<<"dummyx::dummyFunct(d) = "<<dummyx::dummyFunct(d)<<std::endl; std::cout<<"dummyFunct(d) = "<<dummyFunct(d)<<std::endl; // fails with 3.4 and 4.0 std::cout<<"myDummyFunct(d) = "<<myDummyFunct(d)<<std::endl; std::cout<<"mymyDummyFunct(d) = "<<mymyDummyFunct(d)<<std::endl; // fails with 3.4 and 4.0 } When I try to compile this code using g++ version 4.0.2 I get the following errors: testit.cc: In function ‘int main()’: testit.cc:26: error: ‘dummyx::dummyFunct’ cannot be used as a function testit.cc:28: error: ‘dummyx::mymyDummyFunct’ cannot be used as a function I see no reason why such references should not be able to be used as a function. As you see, if it is explicitly namespace-qualified it can be. And according to Koenig rules, the unqualified name should indeed be found and, as operator() is applicable for the found reference, it should be usable as a function. Indeed, this is what version 3.2.3 of g++ does. The above test code compiles fine with g++ version 3.2.3. The errors seem only to occur in versions 3.4 and later (certainly they occur for versions 3.4.5 and 4.0.2.) Additional version information: g++ (GCC) 3.2.3 20030502 (Red Hat Linux 3.2.3-20) g++-3.4 (GCC) 3.4.5 20050809 (prerelease) (Ubuntu 3.4.4-6ubuntu8) g++-4.0 (GCC) 4.0.2 20050808 (prerelease) (Ubuntu 4.0.1-4ubuntu9)
Actually IIRC Koenig lookup only finds functions and not variables. If that is the case we have two issues here. One is we accept invalid and another is that error message is wrong. Note ICC rejects this: t.cc(26): error: identifier "dummyFunct" is undefined std::cout<<"dummyFunct(d) = "<<dummyFunct(d)<<std::endl; // fails with 3.4 ^ t.cc(28): error: identifier "myDummyFunct" is undefined std::cout<<"myDummyFunct(d) = "<<myDummyFunct(d)<<std::endl; ^ t.cc(29): error: identifier "mymyDummyFunct" is undefined std::cout<<"mymyDummyFunct(d) = "<<mymyDummyFunct(d)<<std::endl; // fails ^
The current C++ standard says that Koenig applies "when an unqualified name is used as the postfix-expression in a function call" which from what I've read, must include the case of functoids/functors and references to functoids/functors. It is true that some people seem to be arguing that the standard be changed to restrict Koenig to only functions, a view which seems to me rather unfortunate. However the fact remains that the current standard allows functors and the g++ compiler complies with this by allowing functors. The issue is that references to functors appear to be broken in the most recent versions of g++. I have written much code that relies on g++ finding references to functors through Koenig lookup. This code compiled fine with version 3.2. The problem only arose when I tried to update to the 4.0 compiler.
Subject: Re: Koenig found functoid ref, but "cannot be used as a function" "pinskia at gcc dot gnu dot org" <gcc-bugzilla@gcc.gnu.org> writes: | Actually IIRC Koenig lookup only finds functions and not variables. That is incorrect. There is an active core language issue on "argument dependent name lookup specification." -- Gaby
this issue should be resolved one way of the other based on the core issue about argument dependent lookup specification, when a non-function is found. The "obvious" solution would be to do overload resolution based on the signatures (whether actual function, constructor, function objects, or references to those). However, all that needs tracking the open core issue.
Gaby, can you help me with this old issue? I can't find any DR still open in this area, and we behave exactly like current clang & icc, that is we reject the last three lines (about unqualified dummyFunct, myDummyFunct, and mymyDummyFunct). Can we resolve this bug?
The standard says: When considering an associated namespace, the lookup is the same as the lookup performed when the associated namespace is used as a qualifier (3.4.3.2) except that: - [...] - [...] - All names except those of (possibly overloaded) functions and function templates are ignored. So non-functions are ignored.
See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#218 for the rationale.
Thanks Jon!
Thanks Jonathan for the information on the updated standard and the rationale behind restricting Koenig to actual functions and function templates. In one way it is a bit of a pity - it does make functors second-class citizens compared to functions - but the linked document explains some additional considerations, namely the risk of over-visibility of names. Perhaps it is a reasonable choice for now. Hopefully a better solution will be introduced down the track (maybe extending it to functors, while at the same time narrowing/allowing-control-over namespaces to be looked up).
I wouldn't hold your breath unfortunately. There are at least two opposing views on how to "fix" ADL within the standard committee and no consensus on what (if anything) should be done.