multiple virtual inheritance and variadic template - c++

In my project I played with the following design :
enum {
A = 1, B = 2, C = 4
};
struct Foo { int foo; };
template <int> struct Bar;
template <> struct Bar<A> : public virtual Foo { int a; };
template <> struct Bar<B> : public virtual Foo { int b; };
template <> struct Bar<C> : public virtual Foo { int c; };
Now I can do something fun like :
template <> struct Bar<A|B> : public A, public B {};
template <> struct Bar<A|C> : public A, public C {};
template <> struct Bar<B|C> : public B, public C {};
template <> struct Bar<A|B|C> : public A, public B, public C {};
So that I can write :
Bar<A|C> bar;
bar.foo = 2;
bar.a = 1;
bar.c = 2;
Now I would like the generation of the combination classes Bar<X|Y|Z|..> to be automatically done when the user creates such an instance.
Is this possible using some template magic ?
Something along the lines of :
template <int N, class ...Classes> struct Bar<N> : public Classes... {};
template <int N> struct Bar<N> : public Bar<N, generate_classes<N> > {};
where generate_classes would be able to generate the list of classes Bar<N> should inherit from.

No need in fancy schmancy SFINAE, parameter packs or any such dark wizardry.
enum {
A = 1, B = 2, C = 4
};
struct Foo { int foo; };
template <unsigned int> struct Bar; // unsigned because bit fiddling
template <> struct Bar<A> : public virtual Foo { int a; };
template <> struct Bar<B> : public virtual Foo { int b; };
template <> struct Bar<C> : public virtual Foo { int c; };
template <unsigned int i> struct Bar :
public Bar<i & ~(i-1)>, // only least significant set bit
public Bar<i & (i-1)> // all other set bits
{ };
// checking
int main ()
{
Bar<A|B|C> abc;
abc.a = 0; // ok
abc.b = 0; // ok
abc.c = 0; // ok
Bar<A|B> ab;
ab.a = 0; // ok
ab.b = 0; // ok
ab.c = 0; // error
Bar<A|C> ac;
ac.a = 0; // ok
ac.b = 0; // error
ac.c = 0; // ok
Bar<9> x; // error
}

Instead of thinking about somehow generating a list of classes to be inherited you can think of it as choosing them. This one should be inherited, this one shouldn't. This can be achieved by static dispatching through template parameter. So we get a template that based on a bool parameter gives either T or an empty class. It is likely to be optimized (it may even be guaranteed in this case, but I'm not sure what exact requirements given by the standard are) by empty base optimization so there is no memory overhead.
#include <iostream>
enum {
A = 1, B = 2, C = 4
};
template <class T, bool Enable>
struct or_empty;
template <class T>
struct or_empty<T, false>
{
struct empty {};
using type = empty;
};
template <class T>
struct or_empty<T, true>
{
using type = T;
};
template <class T, bool Enable>
using or_empty_t = typename or_empty<T, Enable>::type;
struct Foo { int foo; };
template <int I> struct Bar :
public or_empty_t<Bar<A>, I&A>,
public or_empty_t<Bar<B>, I&B>,
public or_empty_t<Bar<C>, I&C> {};
template <> struct Bar<A> : public virtual Foo { int a; };
template <> struct Bar<B> : public virtual Foo { int b; };
template <> struct Bar<C> : public virtual Foo { int c; };
int main()
{
Bar<A|C> bar;
bar.foo = 2;
bar.a = 1;
// bar.b = 2; error
bar.c = 2;
std::cout << bar.foo << ' ' << bar.a << ' ' << bar.c << '\n';
std::cout << sizeof(Bar<A>) << ' ' << sizeof(Bar<A|B>) << ' ' << sizeof(Bar<A|B|C>) << '\n';
}
Demo: http://coliru.stacked-crooked.com/a/f170fbd873739c38

Some machinery to do compile-time unpacking of flags:
enum flag_e { None = 0, A = 1, B = 1<<1, C = 1<<2 };
template<flag_e...>
struct flags {using type=flags; constexpr flags(){}};
template<flag_e>
struct flag{using type=flag; constexpr flag(){}};
constexpr flags<A,B,C> all_flags{};
template<flag_e...lhs, flag_e...rhs>
constexpr flags<lhs...,rhs...> operator+(flags<lhs...>, flags<rhs...>)
{ return {}; }
template<flag_e lhs, flag_e...rhs>
inline constexpr flags<lhs, rhs...> operator+(flag<lhs>, flags<rhs...>)
{ return {}; }
template<flag_e...lhs, flag_e rhs>
inline constexpr flags<lhs..., rhs> operator+(flags<lhs...>, flag<rhs>)
{ return {}; }
template<flag_e...fs>
inline constexpr flags<fs...> operator+(flag<None>, flags<fs...>)
{ return {}; }
template<flag_e...fs>
inline constexpr flags<fs...> operator+(flags<fs...>, flag<None>)
{ return {}; }
template<flag_e f, flag_e...fs>
inline constexpr auto unpack( flag<f>, flags<fs...> x, flags<> )
-> flags<fs...>
{ return {}; }
template<flag_e f, flag_e...fs, flag_e c0, flag_e...checks>
inline constexpr auto unpack( flag<f> fin, flags<fs...> x, flags<c0, checks...> )
-> decltype( unpack( fin, x+flag<flag_e(f&c0)>{}, flags<checks...>{} ) )
{ return {}; }
template<flag_e f>
inline constexpr auto unpack( flag<f> fin )
-> decltype( unpack( flag<f>{}, flags<>{}, all_flags ) )
{ return {}; }
Then we use it:
template <int> struct Bar;
template <class flags> struct BarImpl;
template <flag_e...fs> struct BarImpl<flags<fs...>>:
Bar<fs>...
{};
template <int flags> struct Bar:
BarImpl<decltype(unpack(flag<flag_e(flags)>{}))>
{};
struct Foo { int foo; };
template <> struct Bar<A> : public virtual Foo { int a; };
template <> struct Bar<B> : public virtual Foo { int b; };
template <> struct Bar<C> : public virtual Foo { int c; };
Live example.
The code that lets you have bundles of flags and individual flags can be made more generic at the cost of mentioning the flag_e type more often.
I made it overly slick, with the ability to say flags<A>+flags<B> and get flags<A,B>, because I like that notation.
I then wrote unpack, which takes flag<A|B> and produces flags<A,B>.
In C++14 and 17 things get slicker, which folds and return type deduction and the like.

Related

Conditionally initialize class variable depending on the template type

Suppose I have the following code:
enum class Type
{
Type32,
Type64
};
template<Type T>
class MyClass
{
public:
using MyType = typename std::conditional<T == Type::Type32, uint32_t, uint64_t>::type;
MyType getSum()
{
MyType sum = 0;
for(size_t i = 0;i < sizeof(arr);i ++)
{
sum += arr[i];
}
return sum;
}
private:
//MyType arr[4] = { 0x1234, 0x5678, 0x9ABC, 0xDEF0 }; // for Type::Type32
//MyType arr[2] = { 0x12345678, 0x9ABCDE }; // for Type::Type64
};
I try to initialize a class variable depends on the template type with the same name but different type and value. How can I do that? I probably looking for a solution that works in c++11.
Here is a simple way:
#include <array>
#include <cstdint>
#include <type_traits>
enum class Type { Type32, Type64 };
template <Type>
struct As128Bits;
template <>
struct As128Bits<Type::Type32> {
using Integer = std::uint32_t;
std::array<Integer, 4> data{0x1234, 0x5678, 0x9ABC, 0xDEF0};
};
template <>
struct As128Bits<Type::Type64> {
using Integer = std::uint64_t;
std::array<Integer, 2> data{0x12345678, 0x9ABCDE};
};
template <Type T>
struct MyClass : private As128Bits<T> {
using Integer = typename As128Bits<T>::Integer;
using As128Bits<T>::data;
Integer getSum() {
Integer sum = 0;
for (auto const val : data) {
sum += val;
}
return sum;
}
};
You can use tag dispatch (with a delegating constructor):
template<Type T>
class MyClass
{
public:
using MyType = typename std::conditional<T == Type::Type32, uint32_t, uint64_t>::type;
// This will call one of the constructors below
MyClass() : MyClass(std::integral_constant<Type, T>{}) {}
MyType getSum() { /* ... */ }
private:
explicit MyClass(std::integral_constant<Type, Type::Type32>) : arr{ 0x1234, 0x5678, 0x9ABC, 0xDEF0 } {}
explicit MyClass(std::integral_constant<Type, Type::Type64>) : arr{ 0x12345678, 0x9ABCDEF0 } {}
MyType arr[T == Type::Type32 ? 4 : 2];
};
you can move different part into separate class and do specialization. (or you can do full class specialization if it fits)
template <Type T>
struct MyData;
template <>
struct MyData<Type::Type32>{
uint32_t arr[4] = { 0x1234, 0x5678, 0x9ABC, 0xDEF0 };
};
template <>
struct MyData<Type::Type64>{
uint64_t arr[2] = { 0x12345678, 0x9ABCDE };
};
template<Type T>
class MyClass: private MyData<T>{
// common functions
};

SFINAE - recursive template

I'm trying to do this:
struct A
{
typedef void NoHalf;
};
struct B : A
{
typedef A Half;
};
struct C : B
{
typedef B Half;
};
template<class T, typename = T::NoHalf> void TEST() { };
template<class T, typename = T::Half> void TEST()
{
TEST<T::Half>();
};
int main()
{
TEST<A>();
TEST<B>();
TEST<C>();
};
So the TEST<C> function should do something with class C, then recurse TEST<B>, then to TEST<A> and stop there. Unfortunately I get bunch of errors like TEST has already been defined and funny enough also TEST identifier not found. What am I doing wrong and how to fix that?
Ok, so here's a solution, quite uglier, but seems working:
struct A
{
typedef void Half;
static const int I = 0;
};
struct B : A
{
typedef A Half;
static const int I = 1;
};
struct C : B
{
typedef B Half;
static const int I = 2;
};
template<class T> std::enable_if_t<std::is_void_v<T> > TEST() { };
template<class T> std::enable_if_t<!std::is_void_v<T> > TEST()
{
printf("%i", T::I);
TEST<T::Half>();
};
int main()
{
TEST<A>();
TEST<B>();
TEST<C>();
};

How to detect whether there is actually a specific member variable in class?

I am purposely using the very same title as this question because I feel that the answer that was accepted does not account for a problem that I am stuck into.
I am looking for a way to detect if some class has some member variable. It is fundamental to note that I am looking for a variable, not a member function or anything else.
Here is the example provided in the question I linked:
template<typename T> struct HasX {
struct Fallback { int x; }; // introduce member name "x"
struct Derived : T, Fallback { };
template<typename C, C> struct ChT;
template<typename C> static char (&f(ChT<int Fallback::*, &C::x>*))[1];
template<typename C> static char (&f(...))[2];
static bool const value = sizeof(f<Derived>(0)) == 2;
};
struct A { int x; };
struct B { int X; };
int main() {
std::cout << HasX<A>::value << std::endl; // 1
std::cout << HasX<B>::value << std::endl; // 0
}
But we will get the very same output if we do something like
template<typename T> struct HasX {
struct Fallback { int x; }; // introduce member name "x"
struct Derived : T, Fallback { };
template<typename C, C> struct ChT;
template<typename C> static char (&f(ChT<int Fallback::*, &C::x>*))[1];
template<typename C> static char (&f(...))[2];
static bool const value = sizeof(f<Derived>(0)) == 2;
};
struct A {
void x()
{
}
};
struct B { int X; };
int main() {
std::cout << HasX<A>::value << std::endl; // 1
std::cout << HasX<B>::value << std::endl; // 0
}
(Please note that in the second example the int x in A was substituted with a member function void x()).
I have no real idea on how to work around this problem. I partially fixed this by doing something like
template <bool, typename> class my_helper_class;
template <typename ctype> class my_helper_class <true, ctype>
{
static bool const value = std :: is_member_object_pointer <decltype(&ctype :: x)> :: value;
};
template <typename ctype> class my_helper_class <false, ctype>
{
static bool const value = false;
};
template <typename T> struct HasX
{
// ...
static bool const value = my_helper_class <sizeof(f <Derived>(0)) == 2, T> :: value;
};
Which actually selects if I am using an object. However, the above doesn't work if there are more overloaded functions with the same name x in my class.
For example if I do
struct A
{
void x()
{
}
void x(int)
{
}
};
Then the pointer is not resolved successfully and the a call to HasX <A> doesn't compile.
What am I supposed to do? Is there any workaround or simpler way to get this done?
The problem is that HasX only checks if the name x exists. The ... gets selected if &C::x is ambiguous (which happens if it matches both in Fallback and T). The ChT<> overload gets selected only if &C::x is exactly Fallback::x. At no point are we actually checking the type of T::x - so we never actually check if x is a variable or function or whatever.
The solution is: use C++11 and just check that &T::x is a member object pointer:
template <class T, class = void>
struct HasX
: std::false_type
{ };
template <class T>
struct HasX<T,
std::enable_if_t<
std::is_member_object_pointer<decltype(&T::x)>::value>
>
: std::true_type { };
If &T::x doesn't exist, substitution failure and we fallback to the primary template and get false_type. If &T::x exists but is an overloaded name, substitution failure. If &T::x exists but is a non-overloaded function, substitution failure on enable_if_t<false>. SFINAE for the win.
That works for all of these types:
struct A {
void x()
{
}
void x(int)
{
}
};
struct B { int X; };
struct C { int x; };
struct D { char x; };
int main() {
static_assert(!HasX<A>::value, "!");
static_assert(!HasX<B>::value, "!");
static_assert(HasX<C>::value, "!");
static_assert(HasX<D>::value, "!");
}

Get size of polymorphic object

I want to be able to get the size of polymorphic object. At the moment I got this:
struct Base {
virtual std::size_t size() const {
return sizeof(*this);
}
};
struct Derived : Base {
virtual std::size_t size() const {
return sizeof(*this);
}
};
Which is literally copy & paste. I want to do better. Suppose I really hate macros and CRTP seems like the only sensible approach. Let us give it a try:
struct SizedBase {
virtual std::size_t size() const = 0;
};
template <typename Type>
struct Sized : virtual SizedBase {
std::size_t size() const override {
return sizeof(Type);
}
};
struct Base : Sized<Base> {};
struct Derived : Base, Sized<Derived> {};
This looks much better, but sadly is ill-formed: Derived contains two final overriders for size() from Base and from Sized<Derived>. We can solve this by inheriting through Sized:
struct SizedBase {
virtual std::size_t size() const = 0;
};
template <typename Type, typename... SizedBases>
struct Sized : virtual SizedBase, SizedBases... {
std::size_t size() const override {
return sizeof(Type);
}
};
struct Base : Sized<Base> {};
struct Derived : Sized<Derived, Base> {};
This works as intended, however gets somewhat confusing in the event of multiple inheritance and prohibits altering accessibility/virtualness of bases.
So, is there a better way?
Not that anyone should really use this, but...
template <typename>
struct None1 {};
template <typename>
struct None2 {};
template <typename T>
struct PrivateBase { using Tpriv = T; using Tprot = None1<T>; using Tpub = None2<T>; };
template <typename T>
struct ProtectedBase { using Tpriv = None1<T>; using Tprot = T; using Tpub = None2<T>; };
template <typename T>
struct PublicBase { using Tpriv = None1<T>; using Tprot = None2<T>; using Tpub = T; };
template <typename K>
struct TriBase : private K::Tpriv, protected K::Tprot, public K::Tpub {};
template <typename T, typename ... Bases>
struct Sized : private Bases::Tpriv..., protected Bases::Tprot..., public Bases::Tpub...
{
virtual size_t size() { return sizeof(T); }
};
struct Foo : Sized<Foo> {};
struct X{};
struct Y{};
struct Bar : Sized<Bar, PrivateBase<X>, ProtectedBase<Y>, PublicBase<Foo>> {};
int main ()
{
Bar b;
Foo* f = &b;
X* x = &b; // error : private base
Y* y = &b; // error : protected base
}
Virtual inheritance is left as an exercise to the reader.
The order of base classes is not preserved, but you should not depend on it anyway.
Something that is a little bit more production-friendly can be implemented like this (this is a rough sketch):
#include <cstdlib>
#include <typeinfo>
#include <unordered_map>
#include <memory>
#include <iostream>
struct myinfo
{
size_t size;
// any other stuff
};
using TypeInfoRef = std::reference_wrapper<const std::type_info>;
struct Hasher
{
std::size_t operator()(TypeInfoRef code) const
{
return code.get().hash_code();
}
};
struct EqualTo
{
bool operator()(TypeInfoRef lhs, TypeInfoRef rhs) const
{
return lhs.get() == rhs.get();
}
};
static std::unordered_map<TypeInfoRef, myinfo, Hasher, EqualTo> typemap;
template <typename K>
struct typemap_initializer
{
typemap_initializer()
{
typemap[typeid(K)] = myinfo{sizeof(K)};
}
};
struct Base
{
virtual ~Base() {}
size_t size() { return typemap[typeid(*this)].size; }
template<typename K, typename... Arg>
friend K* alloc(Arg...);
private:
void* operator new(size_t sz) { return ::operator new(sz); }
};
template<typename K, typename... Arg>
K* alloc(Arg... arg)
{
static typemap_initializer<K> ti;
return new K(arg...);
}
struct Foo : Base {int a;};
struct Bar : Foo {int b; int c;};
int main ()
{
Foo* f = alloc<Foo>();
Bar* g = alloc<Bar>();
std::cout << f->size() << std::endl;
std::cout << g->size() << std::endl;
}
Of course one gives up the familiar Foo* foo = new Foo syntax, but in the era of ubiquitous std::make_shared<> this is not a big problem.

Order of preference for SFINAE template?

I'm trying to implement templated structs that take a version parameter.
Here's a simplified example:
template<int Version, class Enable = void>
struct Foo
{
};
template<int Version, class Enable = void>
struct Bar
{
};
/* Base Version of Foo */
template<int Version>
struct Foo<Version, typename enable_if<(Version > 0)>::type>
{
int i;
};
/* Base Version of Bar */
template<int Version>
struct Bar<Version, typename enable_if<(Version > 0)>::type>
{
Foo<Version> foo;
float f;
};
/* Version 2 of Bar */
template<int Version>
struct Bar<Version, typename enable_if<(Version >= 2)>::type>
{
Foo<Version> foo;
float f;
int extraParam;
};
With this approach, there is ambiguity when I use "Bar<2>", because 2 satisfies both the base version's condition (Version > 0) and the version 2 condition (Version >= 2).
I could change the base to require "Version > 0 && Version < 2", but I was hoping to avoid having to do that everywhere. Is there a better way to tell the compiler "Use the highest matching version" for a given template ?
Using the example link provided by dyp, I was able to solve the problem with recursion.
#include <iostream>
#include <type_traits>
using namespace std;
template<int Version>
struct Foo
{
constexpr static bool is_valid = false;
};
template<int Version>
struct Bar
{
constexpr static bool is_valid = false;
};
struct ValidVersion { constexpr static bool is_valid = true; };
/* Base Version of Foo */
template<>
struct Foo<0> : ValidVersion
{
int i;
};
/* Base Version of Bar */
template<>
struct Bar<0> : ValidVersion
{
Foo<0> foo;
float f;
};
/* Version 2 of Bar */
template<>
struct Bar<2> : ValidVersion
{
Foo<2> foo;
float f;
int extraParam;
int extraParam2;
};
template<template<int V> class _Tp, int Version>
struct VersionSelectorImpl
{
template<class T>
struct wrap { using type = T; };
using type = typename std::conditional<_Tp<Version>::is_valid, wrap<_Tp<Version>>, VersionSelectorImpl<_Tp, Version-1>>::type::type;
};
template<template<int V> class _Tp, int Version>
using VersionSelector = typename VersionSelectorImpl<_Tp, Version>::type;
int main() {
cout << "sizeof(<Bar, 1>): " << sizeof(VersionSelector<Bar, 1>) << '\n';
cout << "sizeof(<Bar, 2>): " << sizeof(VersionSelector<Bar, 2>) << '\n';
}
Output:
sizeof(<Bar, 1>): 12
sizeof(<Bar, 2>): 16