Boost logo

Boost Users :

Subject: [Boost-users] [type_traits] is_convertible bug with gcc 4.3.0
From: Terry G (tjgolubi_at_[hidden])
Date: 2008-11-08 13:03:04


I'm playing with move semantics (still/again).

The following program compiles and runs fine with msvc8 but does not compile
with gcc 4.3.0 when
ENABLE_IS_CONVERTIBLE_CHECK is defined.
Should it?
The problem has something to do with U's copy constructor being private.
I've inluded the compiler output below too.

terry

============================================
#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>
#include <cassert>

template <typename T>
class move_from {
private:
  T* _source;
public:
  explicit move_from(T& x) : _source(&x) { }
  T& get() const { return *_source; }
}; // move_from

#define ENABLE_IS_CONVERTIBLE_CHECK

template <typename T> inline
move_from<T> move(T& x
#ifdef ENABLE_IS_CONVERTIBLE_CHECK
                  , typename boost::enable_if<
                        boost::is_convertible<move_from<T>, T>
>::type* = 0
#endif
)
{ return move_from<T>(x); }

template <typename T>
class U {
  T* _ptr;
public:
  void reset(T* p=0) { delete _ptr; _ptr = p; }
  T* release() { T* rval = _ptr; _ptr = 0; return rval; }
  U() : _ptr(0) { }
  U(T* x) : _ptr(x) { }
  U(move_from<U> x) : _ptr(x.get().release()) { }
  U& operator=(move_from<U> x) { reset(x.get().release()); }
  T* get() const { return _ptr; }
  T* operator->() const { return get(); }
  T& operator*() const { return *get(); }
private:
  explicit U(const U&);
  U& operator=(const U&);
}; // U

int main() {
  U<int> x(new int(1234));
  U<int> z(move(x)); // Seems to convert ok here.
  assert(*z == 1234);
  assert(!x.get());
  return 0;
} // main

============================================

In file included from c:/boost/boost/type_traits.hpp:38, from bug.cpp:1:
  c:/boost/boost/type_traits/is_convertible.hpp:
  In instantiation of '
    const bool boost::detail::is_convertible_basic_impl<
      move_from<U<int> >&, U<int>
>::value'
      : c:/boost/boost/type_traits/is_convertible.hpp:295:
  instantiated from '
    const bool boost::detail::is_convertible_impl<
      move_from<U<int> >, U<int>
>::value'
      c:/boost/boost/type_traits/is_convertible.hpp:418:
  instantiated from 'boost::is_convertible<move_from<U<int> >, U<int> >'
    c:/boost/boost/utility/enable_if.hpp:36:
  instantiated from 'boost::enable_if<
      boost::is_convertible<move_from<U<int> >, U<int> >, void
>' bug.cpp:46:
  instantiated from here c:/boost/boost/type_traits/is_convertible.hpp:136:
    error: no matching function for call to 'U<int>::U(U<int>)'
  bug.cpp:34: note: candidates are: U<T>::U(move_from<U<T> >) [with T = int]
  bug.cpp:33: note: U<T>::U(T*) [with T = int]
  c:/boost/boost/type_traits/is_convertible.hpp:136: error:
    initializing argument 1 of '
    static boost::type_traits::yes_type
      boost::detail::checker<T>::_m_check(T, int)
        [with T = U<int>]'
        from result of 'U<T>::U(move_from<U<T> >) [with T = int]'


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net