What is the status of N2965 - std::bases and std::direct_bases?
As far as I can tell this was rejected we can see this from N3296: C++ FCD Comment Status Rev 6 which has the following comment:
Paper n2965 was largely rejected after the last CD on the grounds there was no associated national body comment, so I am submitting a national body comment this time.
and the disposition ended up being:
REJECTED
There is no consensus to adopt this proposal at this time
We can find a comment from Jonathan Wakely which points us to the gcc patches email about implementing N2965
into gcc and he notes that there is no TR2 anymore.
I don't see any follow-up proposals for this
Status of std::bases and std::direct_bases
The original proposal for std::bases
was rejected, in part because it arrived too late for a then immediately upcoming new standard. Seems like that specific proposal has not resurfaced again.
However, there is a new and more general proposal P0194 Static reflection that includes ways to not only interrogate base classes, but also has a much wider target.
Right now, that proposal contains some types that seems to do something like what the std::bases
proposal suggested:
template <Class T> struct get_public_base_classes;
template <Class T> struct get_accessible_base_classes;
template <Class T> struct get_base_classes;
However (again), in Herb Sutter's latest report from the ISO C++ meeting he projects these kinds of features not to appear in C++20, but perhaps in a future C++23 standard.
using tr2::direct_bases get nth element of result
You can use this simple metafunction to turn the typelist into an std::tuple
:
#include <tr2/type_traits>
#include <tuple>
template<typename T>
struct dbc_as_tuple { };
template<typename... Ts>
struct dbc_as_tuple<std::tr2::__reflection_typelist<Ts...>>
{
typedef std::tuple<Ts...> type;
};
At this point, you could work with it as you would normally work with a tuple. For instance, this is how you could retrieve elements of the type list:
struct A {};
struct B {};
struct C : A, B {};
int main()
{
using namespace std;
using direct_base_classes = dbc_as_tuple<tr2::direct_bases<C>::type>::type;
using first = tuple_element<0, direct_base_classes>::type;
using second = tuple_element<1, direct_base_classes>::type;
static_assert(is_same<first, A>::value, "Error!"); // Will not fire
static_assert(is_same<second, B>::value, "Error!"); // Will not fire
}
Finding base class at compile time
gcc
supports this. See
- Kerrek's answer
- tr2/type_traits
- Andy Prowl's code example
- n2965
- What is the status of N2965 - std::bases and std::direct_bases?
- How to query for all base classes of a class at compile time?
n2965 provides an example.
This simple examples illustrates the results of these type traits. In
the Suppose we have the following class hierarchy:class E {};
class D {};
class C : virtual public D, private E {};
class B : virtual public D, public E {};
class A : public B, public C {};
It follows that
bases<A>::type is tuple<D, B, E, C, E>
Similarly,
direct_bases<A>::type is tuple<B, C>
Andy Prowl's code example is as follows:
#include <tr2/type_traits>
#include <tuple>
template<typename T>
struct dbc_as_tuple { };
template<typename... Ts>
struct dbc_as_tuple<std::tr2::__reflection_typelist<Ts...>>
{
typedef std::tuple<Ts...> type;
};
struct A {};
struct B {};
struct C : A, B {};
int main()
{
using namespace std;
using direct_base_classes = dbc_as_tuple<tr2::direct_bases<C>::type>::type;
using first = tuple_element<0, direct_base_classes>::type;
using second = tuple_element<1, direct_base_classes>::type;
static_assert(is_same<first, A>::value, "Error!"); // Will not fire
static_assert(is_same<second, B>::value, "Error!"); // Will not fire
}
Check if the class has any base class in C++ in compile time
As mentioned in comments you can't do exactly this in standard C++. The closest you get from std library is std::is_base_of
, but it is for testing a specific base class.
But as mentioned here GCC has std::tr2::bases
(and std::tr2::direct_bases
) that solves your question for a generic "has any base" assertion. These came from the N2965 proposal and unfortunately was rejected for std C++.
Here's a sample code showing how you can use this GCC extension to assert just what you want:
#include <tr2/type_traits>
class B {};
class X : public B {};
static_assert(std::tr2::bases<X>::type::empty(),"X");
// doesn't compile because X bases tuple returned is not empty
class Y {};
static_assert(std::tr2::bases<Y>::type::empty(),"Y");
#include <iostream>
using namespace std;
int main() {
return 0;
}
Related Topics
Splitting a String by a Character
How to Get the CPU Usage Per Thread on Windows (Win32)
Why Don't the C or C++ Standards Explicitly Define Char as Signed or Unsigned
Forward Declare a Standard Container
Cast Pointer to Member Function to Normal Pointer
What Do Each Memory_Order Mean
Nested Templates with Dependent Scope
A C++ Implementation That Detects Undefined Behavior
Dll Load Library - Error Code 126
How to Generate All Permutations of an Array in Sorted Order
How to Use a Mask to Iterate Files in a Directory with Boost
Convert Wstring to String Encoded in Utf-8
How to Use String.Substr() Function
How to Sort the Texture Positions Based on the Texture Indices Given in a Wavefront (.Obj) File
Understanding Recursion to Generate Permutations