
Hi Beman, hi all Due to recent changes to the filesystem library now, the header detail/identifier.hpp is now included in my projects and contains the dangerous code segment: template <class Ostream, class Id> typename enable_if< is_base_of< identifier< typename Id::value_type, Id >, Id >, Ostream & >::type operator<<( Ostream & os, const Id & id ) { return os << id.value(); } which breaks all of my codes, since I have a type Id, that has a type member Id::value_type which is an abstract base class. My compiler (Apple gcc-4.0) now tries to instantiate identifier< typename Id::value_type, Id >, which fails because Id::value_type is abstract, and the compiler aborts with an error message. This causes all of our codes to fail to compile with the current CVS head Matthias

Matthias Troyer <troyer@phys.ethz.ch> writes:
Hi Beman, hi all
Due to recent changes to the filesystem library now, the header detail/identifier.hpp is now included in my projects and contains the dangerous code segment:
Is it just dangerous by definition, because it breaks your code on your compiler, or is there something else about it that I'm missing?
template <class Ostream, class Id> typename enable_if< is_base_of< identifier< typename Id::value_type, Id >, Id >, Ostream & >::type operator<<( Ostream & os, const Id & id ) { return os << id.value(); }
which breaks all of my codes, since I have a type Id, that has a type member Id::value_type which is an abstract base class. My compiler (Apple gcc-4.0) now tries to instantiate identifier< typename Id::value_type, Id >, which fails because Id::value_type is abstract, and the compiler aborts with an error message.
Is that a compiler bug? Is your Id in namespace boost?
This causes all of our codes to fail to compile with the current CVS head
That's a problem. -- Dave Abrahams Boost Consulting www.boost-consulting.com

On Nov 12, 2006, at 6:46 PM, David Abrahams wrote:
Matthias Troyer <troyer@phys.ethz.ch> writes:
Hi Beman, hi all
Due to recent changes to the filesystem library now, the header detail/identifier.hpp is now included in my projects and contains the dangerous code segment:
Is it just dangerous by definition, because it breaks your code on your compiler, or is there something else about it that I'm missing?
I feel that any template <class A, class B> ... operator<<(A&, B const&> is quite dangerous. The enable_if is meant to make it safe, but somehow SFINAE is not working here.
template <class Ostream, class Id> typename enable_if< is_base_of< identifier< typename Id::value_type, Id >, Id >, Ostream & >::type operator<<( Ostream & os, const Id & id ) { return os << id.value(); }
which breaks all of my codes, since I have a type Id, that has a type member Id::value_type which is an abstract base class. My compiler (Apple gcc-4.0) now tries to instantiate identifier< typename Id::value_type, Id >, which fails because Id::value_type is abstract, and the compiler aborts with an error message.
Is that a compiler bug?
I'm not sure, it could be: identifier< typename Id::value_type, Id > fails to get instantiated because typename Id::value_type is an abstract type. Should SFINAE catch this without giving an error?
Is your Id in namespace boost?
Yes, it is a shared_ptr<T> where T is an abstract base class. Matthias

Matthias Troyer <troyer@phys.ethz.ch> writes:
On Nov 12, 2006, at 6:46 PM, David Abrahams wrote:
Matthias Troyer <troyer@phys.ethz.ch> writes:
Hi Beman, hi all
Due to recent changes to the filesystem library now, the header detail/identifier.hpp is now included in my projects and contains the dangerous code segment:
Is it just dangerous by definition, because it breaks your code on your compiler, or is there something else about it that I'm missing?
I feel that any
template <class A, class B> ... operator<<(A&, B const&>
is quite dangerous.
Well, okay, we can talk about that, but that's completely irrelevant to a clash with your own Id I think.
The enable_if is meant to make it safe, but somehow SFINAE is not working here.
template <class Ostream, class Id> typename enable_if< is_base_of< identifier< typename Id::value_type, Id >, Id >, Ostream & >::type operator<<( Ostream & os, const Id & id ) { return os << id.value(); }
which breaks all of my codes, since I have a type Id, that has a type member Id::value_type which is an abstract base class. My compiler (Apple gcc-4.0) now tries to instantiate identifier< typename Id::value_type, Id >, which fails because Id::value_type is abstract, and the compiler aborts with an error message.
Is that a compiler bug?
I'm not sure, it could be:
identifier< typename Id::value_type, Id >
fails to get instantiated because typename Id::value_type is an abstract type. Should SFINAE catch this without giving an error?
No.
Is your Id in namespace boost?
Yes, it is a shared_ptr<T> where T is an abstract base class.
That doesn't answer my question. I thought you said you had your own type, "Id," that was getting picked up and used instead of the template parameter? I'm asking whether that's defined in your own namespace or in namespace boost. Maybe you're actually saying that you don't have a type called Id; you just have shared_ptr<T>. Fair enough. I think the correct thing to do is put the definition of class template identifier in its own subnamespace of boost along with the streaming operator (no need for enable_if). It could then be imported into namespace boost with a using declaration... Frankly, I'm not sure that reserving the name boost::identifier is the right thing to do, especially if it's in a detail header. Is this a public interface, or not? If not, it shouldn't be directly in boost::. If so, it should be documented somewhere and it should have passed through a review. Did it? -- Dave Abrahams Boost Consulting www.boost-consulting.com

On Nov 13, 2006, at 4:08 PM, David Abrahams wrote:
Matthias Troyer <troyer@phys.ethz.ch> writes:
On Nov 12, 2006, at 6:46 PM, David Abrahams wrote:
Matthias Troyer <troyer@phys.ethz.ch> writes:
template <class Ostream, class Id> typename enable_if< is_base_of< identifier< typename Id::value_type, Id >, Id >, Ostream & >::type operator<<( Ostream & os, const Id & id ) { return os << id.value(); }
which breaks all of my codes, since I have a type Id, that has a type member Id::value_type which is an abstract base class. My compiler (Apple gcc-4.0) now tries to instantiate identifier< typename Id::value_type, Id >, which fails because Id::value_type is abstract, and the compiler aborts with an error message.
Is that a compiler bug?
Maybe you're actually saying that you don't have a type called Id; you just have
shared_ptr<T>.
Yes, sorry if I was unclear.
Fair enough. I think the correct thing to do is put the definition of class template identifier in its own subnamespace of boost along with the streaming operator (no need for enable_if). It could then be imported into namespace boost with a using declaration...
Frankly, I'm not sure that reserving the name boost::identifier is the right thing to do, especially if it's in a detail header. Is this a public interface, or not? If not, it shouldn't be directly in boost::. If so, it should be documented somewhere and it should have passed through a review. Did it?
It was checked in on November 3rd by Beman Dawes, and I recently realized that now my codes are broken becuase of it. Matthias

On Nov 12, 2006, at 6:46 PM, David Abrahams wrote:
Matthias Troyer <troyer@phys.ethz.ch> writes:
Hi Beman, hi all
Due to recent changes to the filesystem library now, the header detail/identifier.hpp is now included in my projects and contains the dangerous code segment:
Is it just dangerous by definition, because it breaks your code on your compiler, or is there something else about it that I'm missing?
, boost::shared_ptr<my::B> >' src/boost/boost/utility/enable_if.hpp:36: instantiated from 'boost::enable_if<boost::is_base_of<boost::identifier<my::B, boost::shared_ptr<my::B> >, boost::shared_ptr<my::B> >, my::A&>'
Here is an example code exhibiting the bug. As far as I understand section 14.8.2 of the standard, SFINAE does not apply here since Id::value_type in detail/identifier.hpp is a valid type. To me this does not seem to be a compiler bug, but I'm not an expert. #include <boost/shared_ptr.hpp> #include <boost/detail/identifier.hpp> namespace my { struct A {}; struct B { B() {} virtual void foo()=0; virtual ~B() {} }; void operator << (A&, boost::shared_ptr<B> const&) {} } int main() { my::A a; boost::shared_ptr<my::B> b; a << b; } I provide an operator<< for the two types, but still Apple's version of g++-4.0.1 tries to instantiate the general template in detail/ identifier.hpp, and aborts with the following error message: src/boost/boost/detail/identifier.hpp: In instantiation of 'boost::identifier<my::B, boost::shared_ptr<my::B> >': src/boost/boost/type_traits/is_base_and_derived.hpp:141: instantiated from 'boost::detail::is_base_and_derived_impl2<boost::identifier<my::B, boost::shared_ptr<my::B> >, boost::shared_ptr<my::B> >' src/boost/boost/type_traits/is_base_and_derived.hpp:200: instantiated from 'boost::detail::is_base_and_derived_impl<boost::identifier<my::B, boost::shared_ptr<my::B> >, boost::shared_ptr<my::B> >' src/boost/boost/type_traits/is_base_of.hpp:21: instantiated from 'boost::is_base_of<boost::identifier<my::B, boost::shared_ptr<my::B> problem.cpp:22: instantiated from here src/boost/boost/detail/identifier.hpp:61: error: cannot declare field 'boost::identifier<my::B, boost::shared_ptr<my::B> >::m_value' to be of abstract type 'my::B' problem.cpp:8: note: because the following virtual functions are pure within 'my::B': problem.cpp:10: note: virtual void my::B::foo()

Matthias Troyer wrote:
Due to recent changes to the filesystem library now, the header detail/identifier.hpp is now included in my projects and contains the dangerous code segment:
template <class Ostream, class Id> typename enable_if< is_base_of< identifier< typename Id::value_type, Id >, Id >, Ostream & >::type operator<<( Ostream & os, const Id & id ) { return os << id.value(); }
which breaks all of my codes, since I have a type Id, that has a type member Id::value_type which is an abstract base class. My compiler (Apple gcc-4.0) now tries to instantiate identifier< typename Id::value_type, Id >, which fails because Id::value_type is abstract, and the compiler aborts with an error message.
This causes all of our codes to fail to compile with the current CVS head
There are several things going on here, * boost/system/error_code.hpp is now included by the filesystem library, and also presumably asio. boost/system/error_code.hpp in turn uses boost::detail::identifier from boost/detail/identifier.hpp. * When I moved identifier.hpp into boost/detail, I forgot to also move class identifier from namespace boost to namespace boost::detail. That has now been corrected in CVS. * There is a SFINAE issue, as you point out in another post. It works with some compilers but not others. I don't have time at the moment to sort it out, so simply commented out the insert and extractor for now. Thanks for the bug report! --Beman
participants (3)
-
Beman Dawes
-
David Abrahams
-
Matthias Troyer