#9910 closed Bugs (fixed)
is_convertible doesn't compile with inaccessible copy constructor
Reported by: | Owned by: | John Maddock | |
---|---|---|---|
Milestone: | To Be Determined | Component: | type_traits |
Version: | Boost 1.55.0 | Severity: | Problem |
Keywords: | is_convertible | Cc: |
Description
I found a situation where (with gcc-4.8.2
& boost-1.55
) I cannot compile a call to boost::is_convertible
, but I can compile a similar call to std::is_convertible
. This is a bug, unless it is undefined behaviour to pass is_convertible
a type with a private or deleted copy constructor. If it is a bug, it is a boost
bug, not a gcc
bug (explained below).
Here is the discordant code:
#include <type_traits> #include <boost/type_traits/is_convertible.hpp> struct A { A() = default; A(const A&) = delete; // or private: A(const A&) = default; }; struct Ref_A { // proxy reference to A operator A& () { return *_ptr; } A* _ptr; }; int main() { (void)std::is_convertible< Ref_A, A >::value; (void)boost::is_convertible< Ref_A, A >::value; }
I compile with:
{g++|clang++} -std=c++11 -I${BOOST_INCLUDE} -Wall -Wextra -c
With gcc-4.8.2
, the call to boost::is_convertible
fails to compile, complaining that the copy constructor of A is deleted (or private.) The similar call to std::is_convertible
compiles ok (and returns false, but that is irrelevant).
With clang-3.4
, both calls compile. The reason for the discrepancy is that boost/type_traits/intrinsics.hpp
defines the macro BOOST_IS_CONVERTIBLE(T,U)
for clang
, but not for gcc
. Because of that, at the bottom of boost/type_traits/is_convertible.hpp
, clang
uses the macro to implement is_convertible
, whereas gcc
uses is_convertible_impl_dispatch
instead (which is the one that fails). That's why I said this is not a gcc
bug.
A temporary fix I found is to define that macro to defer to std
:
#include <type_traits> #include <boost/type_traits/intrinsics.hpp> #ifndef BOOST_IS_CONVERTIBLE #define BOOST_IS_CONVERTIBLE(T, U) (std::is_convertible<T, U>::value) #endif #include <boost/type_traits/is_convertible.hpp>
Which type_traits
library should we prefer these days, post c++11
? Intuition says std
should be more stable/portable, is that wrong? If it is indeed std
, is there a way (perhaps a macro?) to make boost
mirror std
(I'm talking about type_traits
only). The reason for having such a mirror option is not for new code, but for other boost
libraries which need type_traits
. E.g, I came across this issue from boost::iterator
.
Change History (4)
comment:1 by , 8 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
comment:2 by , 8 years ago
Hi John,
The use of is_abstract<To>
in boost::detail::is_convertible_impl_dispatch_base
disallows
To
to be an array of incomplete types. For example,
struct incomplete; bool b = is_convertible<int, incomplete[]>::value;
produces a compilation error, but this code is fine in C++11.
Michel
Fixed in develop by providing a C++11 conforming version.
I'm not so sure about std::is_convertible being more stable/conforming: there are quite a few bugs in the compiler intrinsics for type_traits that we have to work around: indeed MSVC's std::is_convertible fails this test case!