[iterator] transform_iterator and move-only types

Hi, The following code fails to compile for me: #include <memory> #include <boost/iterator/transform_iterator.hpp> std::unique_ptr<int> foo(int i) { return std::unique_ptr<int>(new int(i)); } int main() { int a[5] = {1, 2, 3, 4, 5}; auto it = boost::make_transform_iterator(a, foo); } The error message I get with GCC 4.8 is pasted below. I think this should work because returning a move-only type from a function by value is a perfectly valid thing to do. Do you agree? Should I file a bug? Thanks, Nate In file included from boost/iterator/iterator_categories.hpp:20:0, from boost/iterator/iterator_adaptor.hpp:14, from boost/iterator/transform_iterator.hpp:12, from test.cpp:2: boost/type_traits/is_convertible.hpp: In instantiation of 'const bool boost::detail::is_convertible_basic_impl<std::unique_ptr<int>&, std::unique_ptr<int> >::value': boost/type_traits/is_convertible.hpp:296:5: required from 'const bool boost::detail::is_convertible_impl<std::unique_ptr<int>, std::unique_ptr<int> >::value' boost/type_traits/is_convertible.hpp:419:1: required from 'struct boost::is_convertible<std::unique_ptr<int>, std::unique_ptr<int> >' boost/mpl/aux_/nested_type_wknd.hpp:26:31: required from 'struct boost::mpl::aux::nested_type_wknd<boost::is_convertible<std::unique_ptr<int>, std::unique_ptr<int> > >' boost/mpl/aux_/preprocessed/gcc/and.hpp:23:8: required from 'struct boost::mpl::aux::and_impl<true, boost::is_convertible<std::unique_ptr<int>, std::unique_ptr<int> >, mpl_::bool_<true>, mpl_::bool_<true>, mpl_::bool_<true> >' boost/mpl/aux_/preprocessed/gcc/and.hpp:48:8: required from 'struct boost::mpl::and_<boost::is_convertible<boost::random_access_traversal_tag, boost::single_pass_traversal_tag>, boost::is_convertible<std::unique_ptr<int>, std::unique_ptr<int> >, mpl_::bool_<true>, mpl_::bool_<true>, mpl_::bool_<true> >' boost/mpl/if.hpp:67:11: [ skipping 6 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ] boost/iterator/detail/facade_iterator_category.hpp:187:8: required from 'struct boost::detail::facade_iterator_category<boost::random_access_traversal_tag, std::unique_ptr<int>, std::unique_ptr<int> >' boost/iterator/iterator_facade.hpp:104:17: required from 'struct boost::detail::iterator_facade_types<std::unique_ptr<int>, boost::random_access_traversal_tag, std::unique_ptr<int>, long int>' boost/iterator/iterator_facade.hpp:621:9: required from 'class boost::iterator_facade<boost::transform_iterator<std::unique_ptr<int> (*)(int), int*, boost::use_default, boost::use_default>, std::unique_ptr<int>, boost::random_access_traversal_tag, std::unique_ptr<int>, long int>' boost/iterator/iterator_adaptor.hpp:261:9: required from 'class boost::iterator_adaptor<boost::transform_iterator<std::unique_ptr<int> (*)(int), int*, boost::use_default, boost::use_default>, int*, std::unique_ptr<int>, boost::use_default, std::unique_ptr<int>, boost::use_default>' boost/iterator/transform_iterator.hpp:74:9: required from 'class boost::transform_iterator<std::unique_ptr<int> (*)(int), int*, boost::use_default, boost::use_default>' test.cpp:12:52: required from here boost/type_traits/is_convertible.hpp:136:23: error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]' static bool const value = sizeof( boost::detail::checker<To>::_m_check(_m_from, 0) ) ^ In file included from c++/4.8.0/memory:81:0, from test.cpp:1: c++/4.8.0/bits/unique_ptr.h:259:7: error: declared here unique_ptr(const unique_ptr&) = delete; ^ In file included from boost/iterator/iterator_categories.hpp:20:0, from boost/iterator/iterator_adaptor.hpp:14, from boost/iterator/transform_iterator.hpp:12, from test.cpp:2: boost/type_traits/is_convertible.hpp:129:41: error: initializing argument 1 of 'static boost::type_traits::yes_type boost::detail::checker<T>::_m_check(T, int) [with T = std::unique_ptr<int>; boost::type_traits::yes_type = char]' static boost::type_traits::yes_type _m_check(T, int); ^

On Fri, Aug 24, 2012 at 11:25 PM, Nathan Ridge <zeratul976@hotmail.com>wrote:
Hi,
The following code fails to compile for me:
#include <memory> #include <boost/iterator/transform_iterator.hpp>
std::unique_ptr<int> foo(int i) { return std::unique_ptr<int>(new int(i)); }
int main() { int a[5] = {1, 2, 3, 4, 5}; auto it = boost::make_transform_iterator(a, foo); }
The error message I get with GCC 4.8 is pasted below.
I think this should work because returning a move-only type from a function by value is a perfectly valid thing to do. Do you agree? Should I file a bug?
Seems reasonable, but upon an initial inspection, this looks like a hiccup in boost::is_convertible...I'm not saying that once that gets sorted out, there won't be something wrong in boost::transform_iterator, but is_convertible should probably be addressed first. In any case, this looks like this same problem that John Bytheway identified in the thread titled "[boost] [type_traits][parameter] Inconsistent boost::is_convertible between gcc and clang". - Jeff
Thanks, Nate
In file included from boost/iterator/iterator_categories.hpp:20:0, from boost/iterator/iterator_adaptor.hpp:14, from boost/iterator/transform_iterator.hpp:12, from test.cpp:2: boost/type_traits/is_convertible.hpp: In instantiation of 'const bool boost::detail::is_convertible_basic_impl<std::unique_ptr<int>&, std::unique_ptr<int> >::value': boost/type_traits/is_convertible.hpp:296:5: required from 'const bool boost::detail::is_convertible_impl<std::unique_ptr<int>, std::unique_ptr<int> >::value' boost/type_traits/is_convertible.hpp:419:1: required from 'struct boost::is_convertible<std::unique_ptr<int>, std::unique_ptr<int> >' boost/mpl/aux_/nested_type_wknd.hpp:26:31: required from 'struct boost::mpl::aux::nested_type_wknd<boost::is_convertible<std::unique_ptr<int>, std::unique_ptr<int> > >' boost/mpl/aux_/preprocessed/gcc/and.hpp:23:8: required from 'struct boost::mpl::aux::and_impl<true, boost::is_convertible<std::unique_ptr<int>, std::unique_ptr<int> >, mpl_::bool_<true>, mpl_::bool_<true>, mpl_::bool_<true> >' boost/mpl/aux_/preprocessed/gcc/and.hpp:48:8: required from 'struct boost::mpl::and_<boost::is_convertible<boost::random_access_traversal_tag, boost::single_pass_traversal_tag>, boost::is_convertible<std::unique_ptr<int>, std::unique_ptr<int> >, mpl_::bool_<true>, mpl_::bool_<true>, mpl_::bool_<true> >' boost/mpl/if.hpp:67:11: [ skipping 6 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ] boost/iterator/detail/facade_iterator_category.hpp:187:8: required from 'struct boost::detail::facade_iterator_category<boost::random_access_traversal_tag, std::unique_ptr<int>, std::unique_ptr<int> >' boost/iterator/iterator_facade.hpp:104:17: required from 'struct boost::detail::iterator_facade_types<std::unique_ptr<int>, boost::random_access_traversal_tag, std::unique_ptr<int>, long int>' boost/iterator/iterator_facade.hpp:621:9: required from 'class boost::iterator_facade<boost::transform_iterator<std::unique_ptr<int> (*)(int), int*, boost::use_default, boost::use_default>, std::unique_ptr<int>, boost::random_access_traversal_tag, std::unique_ptr<int>, long int>' boost/iterator/iterator_adaptor.hpp:261:9: required from 'class boost::iterator_adaptor<boost::transform_iterator<std::unique_ptr<int> (*)(int), int*, boost::use_default, boost::use_default>, int*, std::unique_ptr<int>, boost::use_default, std::unique_ptr<int>, boost::use_default>' boost/iterator/transform_iterator.hpp:74:9: required from 'class boost::transform_iterator<std::unique_ptr<int> (*)(int), int*, boost::use_default, boost::use_default>' test.cpp:12:52: required from here boost/type_traits/is_convertible.hpp:136:23: error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]' static bool const value = sizeof( boost::detail::checker<To>::_m_check(_m_from, 0) ) ^ In file included from c++/4.8.0/memory:81:0, from test.cpp:1: c++/4.8.0/bits/unique_ptr.h:259:7: error: declared here unique_ptr(const unique_ptr&) = delete; ^ In file included from boost/iterator/iterator_categories.hpp:20:0, from boost/iterator/iterator_adaptor.hpp:14, from boost/iterator/transform_iterator.hpp:12, from test.cpp:2: boost/type_traits/is_convertible.hpp:129:41: error: initializing argument 1 of 'static boost::type_traits::yes_type boost::detail::checker<T>::_m_check(T, int) [with T = std::unique_ptr<int>; boost::type_traits::yes_type = char]' static boost::type_traits::yes_type _m_check(T, int); ^

The following code fails to compile for me:
#include <memory> #include <boost/iterator/transform_iterator.hpp>
std::unique_ptr<int> foo(int i) { return std::unique_ptr<int>(new int(i)); }
int main() { int a[5] = {1, 2, 3, 4, 5}; auto it = boost::make_transform_iterator(a, foo); }
The error message I get with GCC 4.8 is pasted below.
I think this should work because returning a move-only type from a function by value is a perfectly valid thing to do. Do you agree? Should I file a bug?
Seems reasonable, but upon an initial inspection, this looks like a hiccup in boost::is_convertible...I'm not saying that once that gets sorted out, there won't be something wrong in boost::transform_iterator, but is_convertible should probably be addressed first.
In any case, this looks like this same problem that John Bytheway identified in the thread titled "[boost] [type_traits][parameter] Inconsistent boost::is_convertible between gcc and clang".
Ah, I see, this works with the latest trunk (which includes the patch posted in that thread). Thanks for the heads up! Regards, Nate
participants (2)
-
Jeffrey Lee Hellrung, Jr.
-
Nathan Ridge