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.