[assign] [type_traits] Bug with is_convertible + list_of

Please take a look at the following small test code: /* 1 */ #include <boost/assign/list_of.hpp> /* 2 */ #include <boost/type_traits/is_convertible.hpp> /* 3 */ #include <iostream> /* 4 */ /* 5 */ template <class T> /* 6 */ bool test1(T value) { /* 7 */ return boost::is_convertible<T, int>::value; /* 8 */ } /* 9 */ /* 10 */ template <class T> /* 11 */ int test2(T value) { /* 12 */ return static_cast<int>(value); /* 13 */ } /* 14 */ /* 15 */ /* 16 */ void main() { /* 17 */ std::cout << test1(2.0) << ", "; /* 18 */ std::cout << test1("Unconvertible") << ", "; /* 19 */ std::cout << test1(boost::assign::list_of(1)(3)) << ", "; /* 20 */ /* 21 */ std::cout << test2(2.0) << std::endl; /* 22 */ // std::cout << test2(boost::assign::list_of(1)(3)) << std::endl; /* 23 */ } When I try to use is_convertible<T, int>::value, with T being a boost::assign::list_of, it wrongly results in a "true" value. This code compiles on MSVC 8.0, and running it gives the following output: 1, 0, 1, 2 If you uncomment line 22 (i.e., if you *really* try to convert the types), the code will not compile, with an error on line 19: boost-1.33.1\include\boost\assign\list_of.hpp(152) : error C2564: 'int' : a function-style conversion to a built-in type can only take one argument boost-1.33.1\include\boost\assign\list_of.hpp(129) : see reference to function template instantiation 'Container boost::assign_detail::converter<DerivedTAssign>::convert<Container>(const Container *,boost::assign_detail::default_type_tag) const' being compiled with [ Container=int, DerivedTAssign=boost::assign_detail::generic_list<int> ] boost-1.33.1\include\boost\assign\list_of.hpp(336) : see reference to function template instantiation 'Container boost::assign_detail::converter<DerivedTAssign>::convert_to_container<Container>(void) const' being compiled with [ Container=int, DerivedTAssign=boost::assign_detail::generic_list<int> ] boost-1.33.1\include\boost\type_traits\is_convertible.hpp(202) : see reference to function template instantiation 'boost::assign_detail::generic_list<T>::operator Container(void) const<To>' being compiled with [ T=int, Container=int, To=int ] boost-1.33.1\include\boost\type_traits\is_convertible.hpp(228) : see reference to class template instantiation 'boost::detail::is_convertible_basic_impl<From,To>' being compiled with [ From=boost::assign_detail::generic_list<int> &, To=int ] boost-1.33.1\include\boost\type_traits\is_convertible.hpp(302) : see reference to class template instantiation 'boost::detail::is_convertible_impl<From,To>' being compiled with [ From=boost::assign_detail::generic_list<int>, To=int ] boost-1.33.1\include\boost\type_traits\is_convertible.hpp(348) : see reference to class template instantiation 'boost::detail::is_convertible_impl_dispatch<From,To>' being compiled with [ From=boost::assign_detail::generic_list<int>, To=int ] test_is_convertible.cpp(7) : see reference to class template instantiation 'boost::is_convertible<From,To>' being compiled with [ From=boost::assign_detail::generic_list<int>, To=int ] test_is_convertible.cpp(19) : see reference to function template instantiation 'bool test1<boost::assign_detail::generic_list<T>>(boost::assign_detail::generic_list<T>)' being compiled with [ T=int ]

Edson Tadeu wrote:
When I try to use is_convertible<T, int>::value, with T being a boost::assign::list_of, it wrongly results in a "true" value.
is_convertible can't care the function body. In this case, it looks into conversion operator of list_of, then says "true". This behavior seems unavoidable in current C++. In fact, you can easily find a type which doesn't exactly work with is_convertible. e.g. shared_ptr. Regards, -- Shunsuke Sogame

Edson Tadeu wrote:
Please take a look at the following small test code:
When I try to use is_convertible<T, int>::value, with T being a boost::assign::list_of, it wrongly results in a "true" value. This code compiles on MSVC 8.0, and running it gives the following output:
1, 0, 1, 2
If you uncomment line 22 (i.e., if you *really* try to convert the types), the code will not compile, with an error on line 19:
As far as is_convertible is concerned this behaviour is unavoidable - assign::list_of *does* contain a suitable member conversion operator, declared as: template< class T > class generic_list { // details snipped... template< class Container > operator Container() const; } The implementation of is_convertible only determines that the declaration exists, it doesn't check that the code contained within the conversion operator actually compiles, and indeed there is no way it can do so. We have asked compiler vendors in the past for a generic __does_this_code_compile(code) operator, but they tend to shudder and run screaming from the room when this is suggested :-( John.
participants (3)
-
Edson Tadeu
-
John Maddock
-
shunsuke