Boost logo

Boost Users :

Subject: [Boost-users] possible bug with boost::is_convertible
From: Matei David (matei_at_[hidden])
Date: 2014-04-10 20:19:53


Hi,

I found a situation where (with gcc 4.8.2 & 1.55) I cannot compile a call to
boost::is_convertible, but I can compile a similar call to std::is_convertible.

I don't know yet if this is a bug. Is it undefined behaviour to pass
is_convertible a type with a deleted or private copy ctor?

Before I go into the details, I'd like to ask, 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.

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, complaining that the
copy ctor of A is deleted (or private.) The similar call to std::is_convertible
compiles ok.

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).

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>

As I was asking above, is there a way to do that systematically for all
type_traits?

Thanks,
M


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