[interprocess] Problematic interface for intrusive_ptr

Hello, as part of its interface intrusive_ptr requires the user to supply two functions: void intrusive_ptr_add_ref(T * p); void intrusive_ptr_release(T * p); These are called from within the implementation of the intrusive_ptr class. When compiling intrusive_ptr_test, cxx complains that intrusive_ptr uses undeclared functions, because the test includes the header file for intrusive_ptr before declaring those two functions. A quick and dirty fix for this would be to move the inclusion of intrusive_ptr.hpp after the declaration of those two functions, and indeed this fixes the compilation error on cxx, but in the long run maybe this implicit interface (relying on the user to somewhere provide two functions before the template is instantiated) should be turned into an explicit interface. Regards, Markus

Markus Schöpflin wrote:
Hello,
as part of its interface intrusive_ptr requires the user to supply two functions:
void intrusive_ptr_add_ref(T * p); void intrusive_ptr_release(T * p);
These are called from within the implementation of the intrusive_ptr class. When compiling intrusive_ptr_test, cxx complains that intrusive_ptr uses undeclared functions, because the test includes the header file for intrusive_ptr before declaring those two functions.
Are you sure that the compiler is correct? A dependent unqualified call is resolved at instantiation time.

Peter Dimov wrote:
Markus Schöpflin wrote:
Hello,
as part of its interface intrusive_ptr requires the user to supply two functions:
void intrusive_ptr_add_ref(T * p); void intrusive_ptr_release(T * p);
These are called from within the implementation of the intrusive_ptr class. When compiling intrusive_ptr_test, cxx complains that intrusive_ptr uses undeclared functions, because the test includes the header file for intrusive_ptr before declaring those two functions.
Are you sure that the compiler is correct? A dependent unqualified call is resolved at instantiation time.
Hmm, have a look at this: ---%<--- template <class T> struct foo { void bar() { foobar(); } }; void foobar() {} void argl() { foo<int> f; f.bar(); } --->%--- Comeau Online has this to say: ---%<--- "ComeauTest.c", line 2: error: identifier "foobar" is undefined void bar() { foobar(); } ^ 1 error detected in the compilation of "ComeauTest.c". --->%--- What do you think? Markus

Peter Dimov wrote:
Markus Schöpflin wrote:
Hmm, have a look at this:
---%<--- template <class T> struct foo { void bar() { foobar(); } };
This call to foobar is not dependent on T. Try
template <class T> struct foo { void bar( T * p ) { foobar( p ); } };
OK, what about this: ---%<--- template <class T> struct foo { T *p; void bar() { foobar(p); } }; void foobar(int *p) {} void argl() { foo<int> f; f.bar(); } --->%--- I think this resembles the situation at hand now. I still get: ---%<--- "ComeauTest.c", line 3: error: identifier "foobar" is undefined void bar() { foobar(p); } ^ detected during instantiation of "void foo<T>::bar() [with T=int]" at line 10 --->%--- And it works if you insert 'void foobar(int *p);' before struct foo. Markus

Markus Schöpflin wrote:
Peter Dimov wrote:
Markus Schöpflin wrote:
Hmm, have a look at this:
---%<--- template <class T> struct foo { void bar() { foobar(); } };
This call to foobar is not dependent on T. Try
template <class T> struct foo { void bar( T * p ) { foobar( p ); } };
OK, what about this:
---%<--- template <class T> struct foo { T *p; void bar() { foobar(p); } };
void foobar(int *p) {}
void argl() { foo<int> f; f.bar(); } --->%---
I don't think lookup works with built-in types. Try the above with e.g. "struct bar{};" instead of "int". / Johan

Johan Nilsson wrote:
Markus Schöpflin wrote:
[...]
---%<--- template <class T> struct foo { T *p; void bar() { foobar(p); } };
void foobar(int *p) {}
void argl() { foo<int> f; f.bar(); } --->%---
I don't think lookup works with built-in types. Try the above with e.g. "struct bar{};" instead of "int".
You are right. Sigh, obviously I don't manage to create a small reproducer for the error seen at http://preview.tinyurl.com/23towf. (Scroll down to the last five errors, ignore the rest, this has been fixed by now.) But yet I have learned by now that usually this compiler knows the standard better than me. Could anyone confirm or deny that this is indeed an error? TIA, Markus

Markus Schöpflin wrote:
Sigh, obviously I don't manage to create a small reproducer for the error seen at http://preview.tinyurl.com/23towf. (Scroll down to the last five errors, ignore the rest, this has been fixed by now.)
Can you please try changing intrusive_ptr_add_ref( detail::get_pointer( m_ptr ) ); to T * p = detail::get_pointer( m_ptr ); intrusive_ptr_add_ref( p ); ? It could be the intermediate get_pointer call that is tricking the compiler into thinking that the call is not dependent.

Peter Dimov wrote:
Markus Schöpflin wrote:
Sigh, obviously I don't manage to create a small reproducer for the error seen at http://preview.tinyurl.com/23towf. (Scroll down to the last five errors, ignore the rest, this has been fixed by now.)
Can you please try changing
intrusive_ptr_add_ref( detail::get_pointer( m_ptr ) );
to
T * p = detail::get_pointer( m_ptr ); intrusive_ptr_add_ref( p );
?
It could be the intermediate get_pointer call that is tricking the compiler into thinking that the call is not dependent.
I modified the constructor into: intrusive_ptr(const pointer &p, bool add_ref = true): m_ptr(p) { if(m_ptr != 0 && add_ref) { T* p = detail::get_pointer(m_ptr); intrusive_ptr_add_ref(p); } } But I still get: cxx: Error: ../../../boost/interprocess/smart_ptr/intrusive_ptr.hpp, line 77: identifier "intrusive_ptr_add_ref" is undefined (undeclared) detected during instantiation of "boost::interprocess::intrusive_ptr<T, VoidPointer>::intrusive_ptr(const boost::interprocess::intrusive_ptr<T, VoidPointer>::pointer &, bool) [with T=n_transitive::X, VoidPointer=VP]" at line 468 of "intrusive_ptr_test.cpp" intrusive_ptr_add_ref(p); --------^ Markus

Markus Schöpflin wrote:
But I still get:
cxx: Error: ../../../boost/interprocess/smart_ptr/intrusive_ptr.hpp, line 77: identifier "intrusive_ptr_add_ref" is undefined (undeclared) detected during instantiation of "boost::interprocess::intrusive_ptr<T, VoidPointer>::intrusive_ptr(const boost::interprocess::intrusive_ptr<T, VoidPointer>::pointer &, bool) [with T=n_transitive::X, VoidPointer=VP]" at line 468 of "intrusive_ptr_test.cpp" intrusive_ptr_add_ref(p); --------^
This is a point of instantiation error. It's caused by intrusive_ptr_add_ref not being defined in one of the associated namespaces of n_transitive::X. Looking at the test, it looks like namespace N, the home of N::base, is the appropriate place for standard-conforming compilers. In http://svn.boost.org/trac/boost/browser/trunk/libs/smart_ptr/test/intrusive_... I've defined intrusive_ptr_* as inline friends of base, but an out of class definition in N will also work.

Peter Dimov schrieb:
Markus Schöpflin wrote:
But I still get:
cxx: Error: ../../../boost/interprocess/smart_ptr/intrusive_ptr.hpp, line 77: identifier "intrusive_ptr_add_ref" is undefined (undeclared) detected during instantiation of "boost::interprocess::intrusive_ptr<T, VoidPointer>::intrusive_ptr(const boost::interprocess::intrusive_ptr<T, VoidPointer>::pointer &, bool) [with T=n_transitive::X, VoidPointer=VP]" at line 468 of "intrusive_ptr_test.cpp" intrusive_ptr_add_ref(p); --------^
This is a point of instantiation error. It's caused by intrusive_ptr_add_ref not being defined in one of the associated namespaces of n_transitive::X. Looking at the test, it looks like namespace N, the home of N::base, is the appropriate place for standard-conforming compilers.
In
http://svn.boost.org/trac/boost/browser/trunk/libs/smart_ptr/test/intrusive_...
I've defined intrusive_ptr_* as inline friends of base, but an out of class definition in N will also work.
Thank you very much for your help, tomorrow I'll try to move those two functions to N to see if it works then. But I still think that this kind of implicit interfacing with client code should be avoided. Or is this considered OK by others? Markus

Peter Dimov schrieb: [...]
Thanks Peter for your explanations.
Markus Schöpflin wrote:
Thank you very much for your help, tomorrow I'll try to move those two functions to N to see if it works then.
But I still think that this kind of implicit interfacing with client code should be avoided. Or is this considered OK by others?
I just followed boost::intrusive_ptr path, but I admit that I really don't understand unqualified calls and ADL. I will move those functions and check several platforms to see if everything is OK.
Markus
Ion

Markus Schoepflin wrote:
Hmm, have a look at this:
---%<--- template <class T> struct foo { void bar() { foobar(); } };
void foobar() {}
void argl() { foo<int> f; f.bar(); }
According to EDG documentation: " The dependent name lookup rules require that nondependent names be looked up at the point of use in the template definition, and that overload resolution be performed on nondependent calls at that point. " Based on the above, I think that EDG is correct in rejecting this program when dependent name lookup is enabled (it is automatically enabled in strict mode) because at the point of use in the template definition of foo, foobar is not visible. cxxosf.zko.hp.com> eccp -c x.cpp cxxosf.zko.hp.com> eccp -c x.cpp --dep_name "x.cpp", line 2: error: identifier "foobar" is undefined void bar() { foobar(); } ^ 1 error detected in the compilation of "x.cpp". cxxosf.zko.hp.com> Boris ----- Original Message ----- From: "Markus Schöpflin" <markus.schoepflin@comsoft.de> To: <boost@lists.boost.org> Sent: Wednesday, October 24, 2007 9:01 AM Subject: Re: [boost] [interprocess] Problematic interface for intrusive_ptr Peter Dimov wrote:
Markus Schöpflin wrote:
Hello,
as part of its interface intrusive_ptr requires the user to supply two functions:
void intrusive_ptr_add_ref(T * p); void intrusive_ptr_release(T * p);
These are called from within the implementation of the intrusive_ptr class. When compiling intrusive_ptr_test, cxx complains that intrusive_ptr uses undeclared functions, because the test includes the header file for intrusive_ptr before declaring those two functions.
Are you sure that the compiler is correct? A dependent unqualified call is resolved at instantiation time.
Hmm, have a look at this: ---%<--- template <class T> struct foo { void bar() { foobar(); } }; void foobar() {} void argl() { foo<int> f; f.bar(); } --->%--- Comeau Online has this to say: ---%<--- "ComeauTest.c", line 2: error: identifier "foobar" is undefined void bar() { foobar(); } ^ 1 error detected in the compilation of "ComeauTest.c". --->%--- What do you think? Markus _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
participants (6)
-
Boris Gubenko
-
Ion Gaztañaga
-
Johan Nilsson
-
Markus Schöpflin
-
Markus Schöpflin
-
Peter Dimov