|
Prev: composition and bad_alloc
Next: Getting address of enclosing object from address of inner object
From: Kimon Hoffmann on 16 Apr 2008 06:45 Hi all, I have a problem overloading a function located in a namespace for a custom type. I have constructed the following example (emulating a preprocessed source file) exhibiting the problem. Although I tried to be concise with it, it's still quite long, so please bear with me: ---------------------------------------------------------------------- // Code included from DefaultImplementation.hpp namespace default_impl { struct DefaultType { /* ... */ }; inline void func(DefaultType const&) { // .. do something ... } } // Code included from Algorithm.hpp namespace algorithm { template<typename T> void cool_algorithm_1(T const& value) { using default_impl::func; // ... func(value); // ... } template<typename T> void cool_algorithm_2(T const& value) { // ... default_impl::func(value); // ... } } // Code included from NotWorking.hpp struct NotWorking { /* ... */ }; namespace default_impl { inline void func(NotWorking const&) { // .. do something else ... } } // Code included from HalfWorking.hpp struct HalfWorking { /* ... */ }; inline void func(HalfWorking const&) { // .. do something else ... } // Code from Main.cpp int main(int, char**) { NotWorking notWorking; // This does not work as the func() overload is not found algorithm::cool_algorithm_1(notWorking); // For the same reason this does not work either algorithm::cool_algorithm_2(notWorking); HalfWorking halfWorking; // This *does* work thanks to ADL algorithm::cool_algorithm_1(halfWorking); // This does not work because of full qualification algorithm::cool_algorithm_2(halfWorking); return 0; } ---------------------------------------------------------------------- It is obvious why the cool_algorithm_X() functions choke when calling func() with a constant NotWorking reference, and it is also clear to me why the correct overload of func() is found from within cool_algorithm_1() in the HalfWorking case. What I'd like to know is whether there is some way to make HalfWorking work with fully qualified calls to func() like the one in cool_algorithm_2(), besides the obvious solution to move HalfWorking together with the function overload into the default_impl namespace. I really appreciate any help on this. Best regards, Kimon -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Alberto Ganesh Barbati on 16 Apr 2008 18:51 Kimon Hoffmann ha scritto: > > It is obvious why the cool_algorithm_X() functions choke when calling > func() with a constant NotWorking reference Well, what you say it's correct, but it is not *that* obvious. Function default_impl::func(NotWorking): 1) is not found in binding phase 1 because it is not visible at the point of definition of the template. (Had it been visible at that point, the program would compile nicely regardless of the fact that NotWorking is in the "wrong" namespace.) 2) is not found in binding phase 2 because in neither cases ADL is triggered (in the first case because default_impl is not an associated namespace of NotWorking and in the second case because of the full qualification) > and it is also clear to me > why the correct overload of func() is found from within > cool_algorithm_1() in the HalfWorking case. Correct, that's because in that case ADL kicks in and the global namespace is an associated namespace of HalfWorking, so the function is found in binding phase 2. > What I'd like to know is whether there is some way to make HalfWorking > work with fully qualified calls to func() like the one in > cool_algorithm_2(), besides the obvious solution to move HalfWorking > together with the function overload into the default_impl namespace. Given that the target function is not defined in namespace default_impl, I don't see how you might refer to it with a name fully qualified with default_impl::. HTH, Ganesh -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Alberto Ganesh Barbati on 17 Apr 2008 07:43 Alberto Ganesh Barbati ha scritto: > Kimon Hoffmann ha scritto: > >> What I'd like to know is whether there is some way to make HalfWorking >> work with fully qualified calls to func() like the one in >> cool_algorithm_2(), besides the obvious solution to move HalfWorking >> together with the function overload into the default_impl namespace. > > Given that the target function is not defined in namespace default_impl, > I don't see how you might refer to it with a name fully qualified with > default_impl::. > Well, of course you could put a using declaration using ::func; in namespace default_impl, but you still need to have the definition of ::foo() visible at the definition point of the algorithm. This would greatly restrict the genericity of the algorithm. HTH, Ganesh -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Kimon Hoffmann on 18 Apr 2008 06:01 Hi all, First of all thanks to Alberto Ganesh Barbati for being so kind to explain the binding in various phases. After leaving the code alone for one day, a solution occurred to me, that is not really pretty, but at least it is working as expected. Here is the revised code: ---------------------------------------------------------------------- // Code included from DefaultImplementation.hpp namespace default_impl { struct DefaultType { /* ... */ }; template<typename T> void func(T const&); template<> inline void func(DefaultType const&) { // .. do something ... } } // Code included from Algorithm.hpp namespace algorithm { template<typename T> void cool_algorithm_1(T const& value) { using default_impl::func; // ... func(value); // ... } template<typename T> void cool_algorithm_2(T const& value) { // ... default_impl::func(value); // ... } } // Code included from Working.hpp struct Working { /* ... */ }; namespace default_impl { template<> inline void func(Working const&) { // .. do something else ... } } // Code from Main.cpp int main(int, char**) { Working working; algorithm::cool_algorithm_1(working); algorithm::cool_algorithm_2(working); return 0; } ---------------------------------------------------------------------- My understanding of why this works as expected is that both calls to func() bind to the primary template forward declaration of func(), because "Specializations don't overload" (see [1]). At link time the individual (implicitly specialized) calls to func() resolve to the explicitly specialized versions of the function and the code links flawlessly. As I said in the introduction, this solution is not very pretty. The first reason is the somewhat unintuitive semantics of function template specializations (again "Specializations don't overload"), as explained by Herb Sutter in his article "Why Not Specialize Function Templates?" [1], and the second reason is that missing specializations are only detected at link time and thus don't produce compiler errors as one would expect, but rather linker errors that might be hard to track down. If I have some time to spare I'll probably restructure the whole thing to make use of the nice workaround mentioned in the abovementioned article. Best regards, Kimon [1] http://www.gotw.ca/publications/mill17.htm -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Kimon Hoffmann on 18 Apr 2008 06:02 Kimon Hoffmann wrote: > > What I'd like to know is whether there is some way to make HalfWorking > work with fully qualified calls to func() like the one in > cool_algorithm_2(), besides the obvious solution to move HalfWorking > together with the function overload into the default_impl namespace. > for the record, the "obvious solution" does not work either, because ADL only applies to unqualified function calls and therefor the fully qualified call to func() from within cool_algorithm_2() will always bind to the wrong overload. Best regards, Kimon -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
|
Next
|
Last
Pages: 1 2 Prev: composition and bad_alloc Next: Getting address of enclosing object from address of inner object |