Boost logo

Boost :

Subject: Re: [boost] [type_traits] revisiting is_virtual_base_of
From: Steven Watanabe (watanabesj_at_[hidden])
Date: 2018-02-02 20:16:38


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


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk