While working on c++/13658, I ran into divergent behavior between icc 7.1 and g++. I think g++ is wrong, and that in the code below, the explicitly specialized function template is the most specialized function, and should be called. By removing the template specialization syntax (ie "template<>"), and trying again, I get something that is considered the most specialized. But, why this and not the other? -benjamin #include <vector> #include <cassert> #define VERIFY assert struct T { int i; }; int swap_calls; namespace std { // Should be most specialized. #if 1 template<> #endif inline void swap(vector<T, allocator<T> >&, vector<T, allocator<T> >&) { ++swap_calls; } } void test01() { bool test __attribute__((unused)) = true; std::vector<T> A; std::vector<T> B; swap_calls = 0; std::swap(A, B); VERIFY(1 == swap_calls); // XXX fails } void test02() { bool test __attribute__((unused)) = true; using namespace std; vector<T> A; vector<T> B; swap_calls = 0; swap(A, B); VERIFY(1 == swap_calls); } int main() { test01(); test02(); return 0; }
Hm, I have a hard time understanding what's going on. Would you mind posting a self-contained example that doesn't make use of odd include files that contain using namespace stuff? W.
Subject: Re: New: most specialized function template vs. non-template function "bkoz at gcc dot gnu dot org" <gcc-bugzilla@gcc.gnu.org> writes: | While working on c++/13658, I ran into divergent behavior between | icc 7.1 and g++. | | I think g++ is wrong, and that in the code below, the explicitly specialized | function template is the most specialized function, and should be called. It looks to me that this is an interaction between "strong using" and specializations: The most specialized swap() (for vector<>) leaves in __gnu_norm:: whereas the most general leaves in std::. Therefore, when you explicitly specialize, the compiler just considers the template in std:: and forgets about the other one in __gnu_norm::; therefore it thinks that you're specializing the one in std::. Which is wrong. It should have collected all swap() reachable through strongly used namespaces. (Recall that strong using says for all purposes except mangling, everything is the same). | By removing the template specialization syntax (ie "template<>"), and trying | again, I get something that is considered the most specialized. But, why this | and not the other? When you remove the explicit specialization marker, you're overloading with an *ordinary* function and overload resolution prefers non-templates over templates when given equal chances. -- Gaby
Subject: Re: most specialized function template vs. non-template function "bangerth at dealii dot org" <gcc-bugzilla@gcc.gnu.org> writes: | ------- Additional Comments From bangerth at dealii dot org 2004-03-09 05:18 ------- | Hm, I have a hard time understanding what's going on. Would you | mind posting a self-contained example that doesn't make use | of odd include files that contain using namespace stuff? Try with this: namespace A { template<class T> X { }; template<class T> void f(X<T>&); // #1 } namespace B { using namespace A __attribute__((trustme)); template<class T> void f(T&); // #2 } struct foo { }; namespace B { template<> void(X<foo>&); // #3 } B::X<int> x; B::f(x); // calls #2 instead of #3 -- Gaby
Is c++/13294 "strongly related" ;) ?
Subject: Re: most specialized function template vs. non-template function >It looks to me that this is an interaction between "strong using" and >specializations: The most specialized swap() (for vector<>) leaves in >__gnu_norm:: whereas the most general leaves in std::. Therefore, when >you explicitly specialize, the compiler just considers the template in >std:: and forgets about the other one in __gnu_norm::; therefore it >thinks that you're specializing the one in std::. Which is wrong. >It should have collected all swap() reachable through strongly used >namespaces. (Recall that strong using says for all purposes except >mangling, everything is the same). Ok, that's what I thought too. Thanks for the clarification, and the smaller testcase. -benjamin
Surely related to PR 13294, which is targeted at 3.4.0.
Gaby, I tried your testcase with mainline, but the code does call your function #3. If I change the attribute to be "strong", then function #1 is called. Is this the bug? I don't know the semantics of strong using.
Subject: Re: most specialized function template vs. non-template function "giovannibajo at libero dot it" <gcc-bugzilla@gcc.gnu.org> writes: | Gaby, I tried your testcase with mainline, but the code does call | your function #3. If I change the attribute to be "strong", then | function #1 is called. Is this the bug? I don't know the semantics | of strong using. If that happens then we have a double bug :-) Yes, the testcasse for the bug is what happens when you use "strong" in the attribute. (Sorry, I should not have been testing a fine point made by Jason a while ago). Thanks for experimenting and correcting the testcase.. -- Gaby
Created attachment 6038 [details] Patch for 14500
I've attached a patch for this bug, which I haven't been able to fully test because I'm on vacation. It would be nice to get this into 3.4.0, since it's a significant lack of functionality in strong using, but it could wait for 3.4.1.
Subject: Re: most specialized function template vs. non-template function >I've attached a patch for this bug, which I haven't been able to fully test >because I'm on vacation. It would be nice to get this into 3.4.0, since it's a >significant lack of functionality in strong using, but it could wait for 3.4.1. I've tested this, and it looks like there are a couple of new failures. FAIL: g++.dg/template/lookup5.C (test for excess errors) FAIL: g++.old-deja/g++.ns/template12.C (test for excess errors) FAIL: g++.old-deja/g++.ns/template13.C (test for excess errors) FAIL: g++.old-deja/g++.pt/lookup10.C (test for excess errors) Where the errors are: FAIL: g++.dg/template/lookup5.C (test for excess errors) Excess errors: /mnt/hd/src/gcc/gcc/testsuite/g++.dg/template/lookup5.C:8: error: specializing `void N::f(T) [with T = int]' in different namespace /mnt/hd/src/gcc/gcc/testsuite/g++.dg/template/lookup5.C:4: error: from definition of `template<class T> void N::f(T)' -benjamin
Created attachment 6051 [details] Revised patch This revised patch only adds two new FAILs, which may or may not be real fails. I'll investigate this today.
Created attachment 6060 [details] This is a testcase that compiles Jason, here's a testcase that we should (IMHO) check in with this patch. The other implementation of namespace association, EDG, had a similar error to g++ pre patch. Should we ask Daveed for his opinion on this? -benjamin
Subject: Re: most specialized function template vs. non-template function On 8 Apr 2004 19:59:47 -0000, "bkoz at gcc dot gnu dot org" <gcc-bugzilla@gcc.gnu.org> wrote: > The other implementation of namespace association, EDG, had a similar > error to g++ pre patch. Should we ask Daveed for his opinion on this? I'm sure EDG was just trying to be compatible with us. Jason
Jason, given the resolution of PR 13294, what is your position on this bug?
Subject: Re: most specialized function template vs. non-template function On 15 Apr 2004 09:45:46 -0000, "giovannibajo at libero dot it" <gcc-bugzilla@gcc.gnu.org> wrote: > Jason, given the resolution of PR 13294, what is your position on this bug? It's still a bug, but it's not worth blocking 3.4.0 for. Jason
Postponed until GCC 3.4.2.
Postponed until GCC 3.4.3.
Postponed until GCC 3.4.4.
Any news on this?
Benjamin, what's the status on this now? W.
Fixed in 4.0. Won't fix in 3.4.6