$include_dir="/home/hyper-archives/boost-users/include"; include("$include_dir/msg-header.inc") ?>
From: David Abrahams (dave_at_[hidden])
Date: 2006-09-06 03:19:01
Tim Robertson <timr_at_[hidden]> writes:
> Hi,
>
> Can anyone explain why the following won't compile (using g++ 3.3.2 
> under Linux):
>
> #include <boost/utility/enable_if.hpp>
> #include <boost/type_traits/is_convertible.hpp>
>
> using namespace std;
>
> struct Foo
> {
>    Foo() {}
>
>    template <typename T>
>    Foo(T const & src,
>        typename boost::enable_if<
>        boost::is_convertible<T,Foo>, void >::type * dummy = 0)
>   {
>     int i = 1;  // filler.
>   }
>
>    template <typename T>
>    Foo(T const & src,
>        typename boost::disable_if<
>        boost::is_convertible<T,Foo>, void >::type * dummy = 0)
>   {
>     int i = 2;  // ditto.
>   }
>
> };
>
> int main()
> {
>    Foo f;
>    Foo f2(f);
>
>    return 0;
> };
>
>
> When I attempt to compile this code with g++ 3.3.2, I get the following 
> error messages:
Well, first of all, neither of those two constructors is a copy ctor
(a copy ctor has the signature Foo(Foo <cv>&) -- no templates), so the
compiler should be instantiating the implicitly-generated copy ctor,
and, I think, accept your code without complaint.
But that's probably not what you meant for it to do.  In this case
it looks like you have a kind of circular dependency problem.  You can
actually learn a lot by reading the error messages. Reversing your
instantiation backtrace, I get:
> test.cpp:36:   instantiated from here
I assume that's the 2nd line of main()
> test.cpp:36:   instantiated from `boost::enable_if<boost::is_convertible<Foo, Foo>, void>'
It's trying to decide if the first ctor is a match
> test.cpp:36:   instantiated from `boost::is_convertible<Foo, Foo>'
To do that it needs to decide the value nested in is_convertible<Foo,Foo>.
> test.cpp:36:   instantiated from `boost::detail::is_convertible_impl_dispatch<Foo, Foo>'
> /boost/boost/type_traits/is_convertible.hpp:228:   instantiated from `boost::detail::is_convertible_impl<Foo, Foo>'
> /boost/boost/type_traits/is_convertible.hpp:128:   instantiated from `boost::detail::is_convertible_basic_impl<Foo&, Foo>'
Inside implementation details of is_convertible:
> /boost/boost/type_traits/is_convertible.hpp: In instantiation of `boost::disable_if<boost::is_convertible<Foo, Foo>, void>':
To determine convertibility it has to check out the ctors and see if
there's one that implicitly converts Foo->Foo
> /boost/boost/type_traits/is_convertible.hpp:128: error: `value' is not a member of type `boost::is_convertible<Foo, Foo>'
In evaluating the applicability of the first ctor, it needs to know
the value nested in is_convertible<Foo,Foo>.  We've been here before!
HTH,
-- Dave Abrahams Boost Consulting www.boost-consulting.com