Boost logo

Boost Users :

From: David Abrahams (dave_at_[hidden])
Date: 2006-09-06 19:15:54


Tim Robertson <timr_at_[hidden]> writes:

> On Sep 6, 2006, at 12:19 AM, David Abrahams wrote:
>
>> 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>'
>
> Yes, everything up to this point was straightforward. The compiler is
> trying to choose between the constructors by instantiating the various
> enable_if templates. Unfortunately, I'm not as familiar with the
> internals of enable_if<> as many of you, and the *next* part was a bit
> confusing...
>
>>
>> To do that it needs to decide the value nested in
>> is_convertible<Foo,Foo>.

Note---^^^^^^^^^^^^^^^^^^^^^^^

>>> 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
>
> ...but it can't do that if the constructors that would perform the
> conversion are themselves enabled/disabled with enable_if?

Almost but, not quite. It's the specific criterion on whose basis
they're enabled/disabled: is Foo convertible to Foo?

The problem is that is_convertible<Foo,Foo>::value is not yet known,
and (aside from the fact that there's an implicitly generated copy
ctor that's a perfect match which the compiler seems to ignore at this
stage, of course) without that ::value the compiler can't decide
whether either of those constructors is a match for a Foo argument.
In fact, we're only checking for that match because we want to know
that very ::value!

>>> /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!
>>
>
> Right. So again, it seems as though it isn't possible to do what I'm
> trying to do.

Sure it is. You could use

  enable_if< mpl::or_<is_same<T,Foo>, is_convertible<T,Foo> >, ... >

Type sameness can be determined without looking at constructors or
even knowing anything about the definition of the type.

> The enable_if<> template requires the use of the class'
> copy constructor. Even if a default copy constructor is provided, the
> compiler still wants to obtain the nested value type in
> is_convertible<>, and it can't do that, because it needs to decide
> between the three copy-constructor-like functions in the class, two of
> which depend on enable_if<> to determine their signatures. Is that the
> correct way to interpret this situation?

Sorta.

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com

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