[type_traits] revisiting is_virtual_base_of

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

[type_traits] revisiting is_virtual_base_of

Boost - Dev mailing list
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


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [type_traits] revisiting is_virtual_base_of

Boost - Dev mailing list
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

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost