Opened 7 years ago
Closed 4 years ago
#11323 closed Bugs (fixed)
is_virtual_base_of fails to build when virtual bases and their ancestors define identical virtual functions
Reported by: | Owned by: | John Maddock | |
---|---|---|---|
Milestone: | To Be Determined | Component: | type_traits |
Version: | Boost 1.57.0 | Severity: | Problem |
Keywords: | Cc: |
Description
The following code snippet fails to build in clang 6.0:
#include <iostream> #include <boost/type_traits.hpp> struct A { virtual void foo() {} }; struct B : public virtual A { virtual void foo() {} }; struct C : public B {}; int main() { std::cout << boost::is_virtual_base_of<B, C>::value << std::endl; return 0; }
This is the compiler error it throws:
/usr/local/include/boost/type_traits/is_virtual_base_of.hpp:55:12: error: virtual function 'A::foo' has more than one final overrider in 'boost_type_traits_internal_struct_X' struct boost_type_traits_internal_struct_X : public Derived, virtual Base (...)
The problem can be temporarily worked around by redefining virtual void foo() {} into boost_type_traits_internal_struct_X, but that does not scale as we would need to know and override every single virtual method that appears both in A and B.
Change History (4)
comment:1 by , 7 years ago
comment:2 by , 7 years ago
I don't see any either... I'll keep thinking too.
BTW, in case somebody seeing this is wondering why we don't simply make foo a pure virtual in A and avoid the issue altogether, let me share a more meaningful example where this becomes a problem.
#include <iostream> #include <boost/type_traits.hpp> // Let's say enabling RTTI is not an option in our platform / project. #define ASSIGN_CLASS_ID() virtual int GetClassId() { return __COUNTER__; } struct A { ASSIGN_CLASS_ID(); }; struct B : public virtual A { ASSIGN_CLASS_ID(); }; struct C : public B { ASSIGN_CLASS_ID(); }; int main() { std::cout << boost::is_virtual_base_of<B, C>::value << std::endl; return 0; }
comment:3 by , 6 years ago
Using apple LLVM 8.0.0, this fails with pure virtual base class as well:
#include <iostream> #include <boost/type_traits.hpp> struct A { virtual void foo() = 0; }; struct B : public virtual A { void foo() override {} }; struct C : public B {}; int main() { std::cout << boost::is_virtual_base_of<B, C>::value << std::endl; return 0; }
fails to compile on my machine. This makes boost::serialize completely unusable in combination with virtual inheritance
comment:4 by , 4 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
Well it's only taken 3 years, but thanks to the "detection idiom" this should now be fixed in develop for all current (post C++11) compilers.
That's nasty, as I assume this could be a common occurrence, but off the top of my head I don't see a way to fix this :(
Will have to think on this.