[type_traits] revisiting is_virtual_base_of
There is a problem with is_virtual_base_of in that it doesn't work especially well - most of the time it works OK, but can be made to fail catastrophically in a few situations, see for example: https://svn.boost.org/trac10/ticket/11323 Now... it turns out that with C++14 and later we now have is_detected which can test the validity of almost any expression... and I'm wondering if there's a cunning way to press this into action to create a more accurate is_virtual_base_of, but I'm having trouble coming up with anything. Any bright ideas? Note that an explicit static_cast can't be tested for, though we can use is_constructible if required. Thanks in advance, John. --- This email has been checked for viruses by AVG. http://www.avg.com
AMDG On 02/02/2018 12:13 PM, John Maddock via Boost wrote:
There is a problem with is_virtual_base_of in that it doesn't work especially well - most of the time it works OK, but can be made to fail catastrophically in a few situations, see for example: https://svn.boost.org/trac10/ticket/11323
Now... it turns out that with C++14 and later we now have is_detected which can test the validity of almost any expression... and I'm wondering if there's a cunning way to press this into action to create a more accurate is_virtual_base_of, but I'm having trouble coming up with anything. Any bright ideas? Note that an explicit static_cast can't be tested for, though we can use is_constructible if required.
Testing for static_cast<Derived*>(Base*) mostly works, except for private (or protected) virtual inheritance. #include <type_traits> template<class T, class U> constexpr bool is_virtual_base_impl(...) { return true; } template<class T, class U, std::void_t<decltype(static_cast<U*>(std::declval<T*>()))>* = nullptr> constexpr bool is_virtual_base_impl(int) { return false; } template<class T, class U> using is_virtual_base_of_t = std::integral_constant< bool, std::is_base_of<T, U>::value && is_virtual_base_impl<T, U>(0) && !is_virtual_base_impl<U, T>(0) >; #include <iostream> class X { }; class Y : virtual public X {}; class Z : private X {}; class A : public X {}; class B : public X {}; class C : public A, public B {}; class D : private virtual X {}; class E : public virtual X {}; class F : public E, public Y {}; int main() { std::cout << is_virtual_base_of_t<X, Y>::value << std::endl; // true std::cout << is_virtual_base_of_t<Y, X>::value << std::endl; std::cout << is_virtual_base_of_t<X, Z>::value << std::endl; std::cout << is_virtual_base_of_t<X, A>::value << std::endl; std::cout << is_virtual_base_of_t<X, C>::value << std::endl; std::cout << is_virtual_base_of_t<X, D>::value << std::endl; // oops std::cout << is_virtual_base_of_t<X, F>::value << std::endl; // true } In Christ, Steven Watanabe
On 02/02/2018 20:16, Steven Watanabe via Boost wrote:
AMDG
On 02/02/2018 12:13 PM, John Maddock via Boost wrote:
There is a problem with is_virtual_base_of in that it doesn't work especially well - most of the time it works OK, but can be made to fail catastrophically in a few situations, see for example: https://svn.boost.org/trac10/ticket/11323
Now... it turns out that with C++14 and later we now have is_detected which can test the validity of almost any expression... and I'm wondering if there's a cunning way to press this into action to create a more accurate is_virtual_base_of, but I'm having trouble coming up with anything. Any bright ideas? Note that an explicit static_cast can't be tested for, though we can use is_constructible if required.
Testing for static_cast<Derived*>(Base*) mostly works, except for private (or protected) virtual inheritance.
Thanks Steven, it turns out there was a PR I'd been sitting on that used just this technique - works an absolute treat for gcc and msvc including for private and protected inheritance, but fails to build in every case for clang :( See https://github.com/boostorg/type_traits/pull/71 Hopefully someone will spot a workaround for clang.... Thanks, John. --- This email has been checked for viruses by AVG. http://www.avg.com
Hopefully someone will spot a workaround for clang....
Never mind, I think I may have one.... John. --- This email has been checked for viruses by AVG. http://www.avg.com
participants (2)
-
John Maddock
-
Steven Watanabe