
Tim Robertson <timr@u.washington.edu> 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