G++ fails when compiling the following program in g++0x mode. It displays "spooky action at a distance" when instantiating the member_ptr template, but I expect the converting assignment operator from weak_ptr to be selected instead. -------------------------8<----------------------- #include <type_traits> class A { }; class B : public A { }; class C { }; namespace gc { template <typename T> class member_ptr; } template <typename T> class weak_ptr { public: weak_ptr() {} template <typename X> weak_ptr(const weak_ptr<X>& v) {} weak_ptr(const weak_ptr&) = default; weak_ptr(const gc::member_ptr<T>& v); ~weak_ptr() = default; // ------------------ weak_ptr& operator =(const weak_ptr&) = default; template <typename X> weak_ptr& operator =(const weak_ptr<X>& v) { return *this; } }; namespace gc { template <typename T> class member_ptr { static_assert(std::is_base_of<C, T>::value, "spooky action at a distance"); }; } int main(int argc, char *argv[]) { weak_ptr<A> ap1; weak_ptr<B> bp1; ap1 = bp1; return 0; } -------------------------8<-----------------------
let's try to simplify the issue as much as possible... are defaulted / deleted functions really necessary to trigger the bug? Thus, is c++0x mode really necessary?
The below, not using any header neither C++0x mode (very likely can be further reduced), doesn't compile with mainline and 4_3-branch, does with EDG-based compilers in strict mode: template<bool> class __static_assert { }; template<> class __static_assert<false>; template<typename T, typename U> struct __are_same { static const bool value = false; }; template<typename T> struct __are_same<T, T> { static const bool value = true; }; class A { }; class B : public A { }; class C { }; namespace gc { template <typename T> class member_ptr; } template <typename T> class weak_ptr { public: weak_ptr() {} template <typename X> weak_ptr(const weak_ptr<X>& v) {} weak_ptr(const gc::member_ptr<T>& v); template <typename X> weak_ptr& operator=(const weak_ptr<X>& v) { return *this; } }; namespace gc { template <typename T> class member_ptr { __static_assert<__are_same<C, T>::value> sa; }; } int main() { weak_ptr<A> ap1; weak_ptr<B> bp1; ap1 = bp1; }
Volunteers for a better Summary?
Jason, are you willing to help triaging this one?
Sorry, CC-ed Jakub instead of Jason ;)
This is not a SFINAE issue, the bug is that we shouldn't be instantiating member_ptr in the first place in order to resolve the operator= overload.
Subject: Bug 39413 Author: jason Date: Wed Nov 4 22:29:35 2009 New Revision: 153920 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=153920 Log: PR c++/39413 * search.c (lookup_base): Don't complete_type (base). Added: trunk/gcc/testsuite/g++.dg/template/overload11.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/search.c trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/g++.dg/template/nested3.C
Fixed for 4.5.0.