Unreal Engine 5 macros FORVALUE (DETECTED_MEMBER, CheckField) [closed] - c++

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 months ago.
Improve this question
Unreal Engine 5
Macro code solve the problem of reading a variable from an array of int32 Ids
template< class T >
static bool IsArray(T A){return std::is_array<A>::value;}
template< class T >
static bool IsStruct(T A){return std::is_struct<A>::value;}
#define FORVALUE(Value, Field) bool Fv(){ \
bool B=false; \
if(UILbr::IsStruct(Value)){FString S=#Struct; B=S.Find(#Field)>-1; if(B){Value=Value.Field;}} \
bool B=UILbr::IsArray(Value) && Value.IsValidIndex(Id); \
if(B){Value=Value[Id];} \
return B; \
}
/* Library (Instance Variable Saver) */
UCLASS(BlueprintType) class IVS_API UILbr:public UBlueprintFunctionLibrary{GENERATED_UCLASS_BODY()
static TArray<FString> InStrings(FBlns V){return BlnsToStrs(V.V);}
static TArray<FString> InStrings(FBlnsA V){return BlnsAToStrs(V);}
static TArray<FString> InStrings(FBrss V){return BrssToStrs(V.V);}
static TArray<FString> InStrings(FBrssA V){return BrssAToStrs(V);}
template <typename A>
static TArray<FString> InStrings(A V){return {InString(V)};}
static FString InString(bool V){return BlnToStr(V);}
static FString InString(FBlns V){return V.ToString();}
static FString InString(FBlnsA V){return V.ToJson();}
static FString InString(FSlateBrush V){return BrsToStr(V);}
static FString InString(FBrss V){return V.ToString();}
static FString InString(FBrssA V){return V.ToJson();}
}
#define ISSI(T) TArray < FString > UV## T::InStringsIds_Implementation(FI32Ss Ids, bool & B) { \
int32 C = Ids.Num(); \
auto A = V; \
for (int32 & Id: Ids.V) { \
B = FORVALUE(A, V); \
if (B) { \
if (Id == C) { \
break; \
} \
} else { \
break; \
} \
} \
if (C == 0) { \
B = true; \
} \
return UILbr::InStrings(A); \
}
please correct the code FString S=#Struct; B=S.Find(Field)>-1; if(B){Value=Value.Field;}
Code solve the problem of reading a variable from an array of int32 Ids
template< class T >
static bool IsArray(T A){return std::is_array<A>::value;}
template< class T >
static bool IsStruct(T A){return std::is_struct<A>::value;}
template< class T, typename R >
static bool ForValue(T &A, R V, int32 Id){
if(UILbr::IsStruct(A)){A=A.V;} //structvar.member
bool B=UILbr::IsArray(A) && A.IsValidIndex(Id);
if(B){A=A[Id];}
return B;
}
#define ISSI(T) TArray < FString > UV## T::InStringsIds_Implementation(FI32Ss Ids, bool & B) {
int32 C = Ids.Num();
auto A = V;
for (int32 & Id: Ids.V) {
B = UILbr::ForValue(A, V, Id);
if (B) {
if (Id == C) {
break;
}
} else {
break;
}
}
if (C == 0) {
B = true;
}
return UILbr::InStrings(A);
}
Minimized the input data to make it easier to solve the problem
https://www.onlinegdb.com/online_c++_compiler
#include <iostream>
#include <type_traits>
using namespace std;
#define DETECTED_MEMBER(member_name, member_field) bool detected_member(member_name){return member_name.member_field? true: false;}
struct A{A(){}; float v;};
struct B{B(){}; int v;};
int main()
{
//---- true/false
cout<< "DETECTED_MEMBER B.v ? "
<< DETECTED_MEMBER(B,v) <<endl; //true
//---- true/false
cout<< "DETECTED_MEMBER A.v ? "
<< DETECTED_MEMBER(A,v) <<endl; //true
//---- true/false
cout<< "DETECTED_MEMBER A.w ? "
<< DETECTED_MEMBER(A,w) <<endl; //false
}

It would be (the variable in which we are looking for was called V to true)
static bool HasV(T X) {
template<class T> struct HV {
struct Fallback{ int V; }; // introduce member name "V"
struct Derived : T, Fallback{};
template<typename C, C> struct ChT;
template<typename C> static char (&f(ChT<int Fallback::*, &C::V>*))[1];
template<typename C> static char (&f(...))[2];
static bool const value = sizeof(f<Derived>(0)) == 2;
};
return HV<T>::value;
}
It became (we ignore the variable in which we are looking for)
template<typename T, typename = void>
struct HV : std::false_type { };
template<typename T>
struct HV<T, decltype(std::declval<T>().V, void())> : std::true_type { };
template<typename T>
static bool HasV(T X) { return HV<T>::value; }

Related

Workaround for selecting template function implementation on MSVC++ 10.0

My purpose is to select different function implementation based on the memeber variable of data structure. I use member selection idiom "CREATE_MEMBER_DETECTOR" to detect if a data struct has certain member. In my case is to detect member base inside struct A_t and B_t (both of which has it) and member play_id inside base (A_t does not have play_id).The implementation below works on compiler MSVC++ 14.24. How can I make it work also on the old compiler MSVC++ 10.0, which yields tons of error on visual studio 2010. Some features in funtion template select_play_id are not supported
// templ_derive.h
#include <type_traits>
#include <cstdio>
struct A_base_t {
int id;
};
struct A_t {
A_base_t base;
};
struct B_base_t {
int play_id;
};
struct B_t {
B_base_t base;
};
#define CREATE_MEMBER_DETECTOR(X) \
template<typename T> class Detect_##X { \
struct Fallback { int X; }; \
struct Derived : T, Fallback { }; \
\
template<typename U, U> struct Check; \
\
typedef char ArrayOfOne[1]; \
typedef char ArrayOfTwo[2]; \
\
template<typename U> static ArrayOfOne & func(Check<int Fallback::*, &U::X> *); \
template<typename U> static ArrayOfTwo & func(...); \
public: \
typedef Detect_##X type; \
enum { value = sizeof(func<Derived>(0)) == 2 }; \
};
CREATE_MEMBER_DETECTOR(base);
CREATE_MEMBER_DETECTOR(play_id);
template<typename T, bool>
struct use_base_s {
static void valid(T data) {
printf("bast t \n");
}
};
template<typename T>
struct use_base_s <T, true> {
static void valid(T data) {
printf("no base t \n");
}
// U = T and decltype(U::base) do not work!
template<typename U = T>
static void select_play_id(U data,
typename std::enable_if<Detect_play_id<decltype(U::base)>::value,
std::nullptr_t>::type = nullptr) {
printf("has player_id t \n");
return;
}
template<typename U = T>
static void select_play_id(U data,
typename std::enable_if<!Detect_play_id<decltype(U::base)>::value,
std::nullptr_t>::type = nullptr) {
printf("no player_id t \n");
return;
}
};
// main.cpp
#include "templ_derive.h"
int main() {
A_t a_o = A_t();
B_t b_o = B_t();
use_base_s<A_t, Detect_base<A_t>::value>::select_play_id(a_o);
use_base_s<B_t, Detect_base<B_t>::value>::select_play_id(b_o);
}
really appreciate Any help!

How to check with SFINAE if a member exists, without knowing the member's type?

In pre-C++11 code, if I'm looking for a member variable whose type I don't know, how can I use SFINAE to check if the member exists?
Here's an example using Member detector idiom that you asked for:
template<typename T>
struct has_x {
typedef char(&yes)[1];
typedef char(&no)[2];
// this creates an ambiguous &Derived::x if T has got member x
struct Fallback { char x; };
struct Derived : T, Fallback { };
template<typename U, U>
struct Check;
template<typename U>
static no test(Check<char Fallback::*, &U::x>*);
template<typename U>
static yes test(...);
static const bool value = sizeof(test<Derived>(0)) == sizeof(yes);
};
#include <iostream>
struct A { private: int x; }; // works with private, too
struct B { const char x; };
struct C { void x() volatile ; };
struct D : A { };
struct E {};
struct F : A, B {}; // note that &F::x is ambiguous, but
// the test with has_x will still succeed
int main()
{
std::cout
<< has_x<A>::value // 1
<< has_x<const B>::value // 1
<< has_x<volatile C>::value // 1
<< has_x<const volatile D>::value // 1
<< has_x<E>::value // 0
<< has_x<F>::value; // 1
}
Live test.
It should work with MSVC, too.
Here's a solution that I've checked on newer versions of GCC and Clang, as well as on both newer and older versions of Visual C++:
#if defined(_MSC_VER) && _MSC_VER < 1400
#define GEN_MEMBER_CHECKER(Prefix, Member) \
template<class T> struct Prefix##Member \
{ enum { __if_not_exists(T::Member) { value = 0 } __if_exists(T::Member) { value = 1 } }; };
#else
#define GEN_MEMBER_CHECKER(Prefix, Member) \
template<class T> struct Prefix##Member; \
template<class T> struct Prefix##Member<T const> : Prefix##Member<T> { }; \
template<class T> struct Prefix##Member<T volatile> : Prefix##Member<T> { }; \
template<class T> struct Prefix##Member<T volatile const> : Prefix##Member<T> { }; \
template<class T> struct Prefix##Member<T &> : Prefix##Member<T> { }; \
template<class T> struct Prefix##Member<T *> { enum { value = 0 }; }; \
template<> struct Prefix##Member<void> \
{ \
private: \
template<class T> static unsigned char (&test(int, T const &))[1U + 1U]; \
static unsigned char (&test(int, ...))[1U]; \
public: \
template<class T> \
static unsigned char (&check(int, Prefix##Member<T> *))[1U + sizeof(test(0, &T::Member))]; \
static unsigned char (&check(int, ...))[1U]; \
}; \
template<class T> struct Prefix##Member \
{ enum { value = sizeof(Prefix##Member<void>::check(0, (Prefix##Member *)0)) > 2U }; }
#endif
Example:
#include <stdio.h>
GEN_MEMBER_CHECKER(member_check_, Member);
struct HasMember { int Member; };
struct DoesntHaveMember { };
int main()
{
printf("%u %u\n",
member_check_Member<HasMember>::value,
member_check_Member<DoesntHaveMember>::value);
}
Output:
1 0

Extending enum types [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Extending enums in C++?
I am using a library which defines its own set of errors as an enum type.
enum error_type {...}
The library also has a function which takes that enum type, and prints the error.
void set_status(error_type new_error)
If I want to define my own error, and give it to the set_status function, is it possible to extend the error_type enum somehow, or maybe override it?
There might be some sharp edges, but I think this should work for you:
#include<iostream>
// Helper struct
template<typename T, int N, typename... LIST>
struct whereInType {
static const int index = -1;
};
template<typename T, int N, typename HEAD, typename... TAIL>
struct whereInType<T,N,HEAD,TAIL...> {
static const int index = whereInType<T, N+1, TAIL...>::index;
};
template<typename T, int N, typename... TAIL>
struct whereInType<T,N,T,TAIL...> {
static const int index = N;
};
// The actual union type
template<typename... ENUMS>
class enum_union {
public:
template<typename ENUM>
constexpr enum_union(ENUM val) :
which_enum(whereInType<ENUM,0,ENUMS...>::index),
value(val) {}
constexpr operator long long(){
return static_cast<long long>(which_enum)<<32 | value;
}
template<typename ENUM, int IGNORE=0>
constexpr bool operator==(const ENUM& e) {
return *this == enum_union<ENUMS...>(e);
}
template<int IGNORE=0>
constexpr bool operator==(const enum_union<ENUMS...>& oth) {
return which_enum==oth.which_enum && value==oth.value;
}
template<typename T>
constexpr bool operator!=(const T& oth) {
return !(*this == oth);
}
private:
int which_enum;
int value;
};
// An example usage
enum normal_errors {
E_OUTOFMEMORY,
E_IOERROR
};
enum weird_errors {
E_OUTOFAARDVARKS,
E_DIVIDEBYCUCUMBER
};
typedef enum_union<normal_errors, weird_errors> any_error;
// Some tests
void print(any_error e) {
switch(e) {
case any_error(E_OUTOFMEMORY):
std::cout << "Out of Memory\n";
break;
case any_error(E_IOERROR):
std::cout << "I/O Error\n";
break;
case any_error(E_OUTOFAARDVARKS):
std::cout << "WE NEED AARDVARKS!!! NOW!!!!!\n";
break;
case any_error(E_DIVIDEBYCUCUMBER):
std::cout << "please reinstall universe\n";
break;
}
}
main(){
print(E_OUTOFMEMORY);
print(E_IOERROR);
print(E_OUTOFAARDVARKS);
print(E_DIVIDEBYCUCUMBER);
if (any_error(E_OUTOFMEMORY) == E_OUTOFAARDVARKS) {
std::cout<<"bad\n";
}else{
std::cout<<"good\n";
}
if (any_error(E_OUTOFMEMORY) != E_OUTOFAARDVARKS) {
std::cout<<"good\n";
}else{
std::cout<<"bad\n";
}
if (any_error(E_OUTOFMEMORY) == E_OUTOFMEMORY) {
std::cout<<"good\n";
}else{
std::cout<<"bad\n";
}
if (any_error(E_OUTOFMEMORY) != E_OUTOFMEMORY) {
std::cout<<"bad\n";
}else{
std::cout<<"good\n";
}
}

Template specialization for char pointer?

boost::lexical_cast is a great tool but in my application I ran into a limitation in string -> bool conversion that is bugging me. I need to convert all strings like "0", "false" and "FALSE" into false and "1", "true" and "TRUE" into true.
boost::lexical_cast only support conversion from/to "0" and "1". So my idea was to write my own conversion function which seems to work fine:
bool str_to_bool(const std::string &str)
{
if(str == "1" || str == "true" || str == "TRUE")
return true;
else if(str == "0" || str == "false" || str == "FALSE")
return false;
else
throw std::runtime_error("Bad cast from std::string to bool!");
}
Now I wan to write a wrapper round boost::lexical_cast and write my own template specializations for it. Here is what I've got so far:
template<typename Target, typename Source>
inline Target my_cast(const Source& src)
{
return boost::lexical_cast<Target>(src);
}
template<>
inline bool my_cast(const std::string& src)
{
return str_to_bool(src);
}
This works great for integers or std::string but obviously fails for string literals or character pointers:
int main(int argc, char* argv[])
{
std::cout << my_cast<bool>(1) << std::endl; //OK
std::cout << my_cast<bool>(std::string("true")) << std::endl; //OK
std::cout << my_cast<bool>("true") << std::endl; //Fail!
return 0;
}
So I tried to write another specialization for char * but it fails to compile!
//does not compile!
template<>
inline bool my_cast(const char*& src)
{
return str_to_bool(src);
}
What is the correct way to support both std::string and char *?
EDIT 1: the title was stupid. Fixed it.
EDIT 2: I borrowed a solution from boost itself. Posted as a new answer.
If you say this:
template<>
inline bool my_cast<bool, std::string>(std::string const & src)
{
return str_to_bool(src);
}
template<>
inline bool my_cast<bool, const char *>(const char * const & src)
{
return str_to_bool(src);
}
Then at least you can make the following work:
int main(int argc, char* argv[])
{
const char * const q = "true";
std::cout << my_cast<bool>(q) << std::endl; //Fail!
return 0;
}
Update: Voila:
typedef char FT[5];
template<>
inline bool my_cast<bool, FT>(const FT & src)
{
return str_to_bool(src);
}
Here is a solution that works. I got the idea from boost::lexical_cast itself:
template<class T>
struct array_to_pointer_decay
{
typedef T type;
};
template<class T, std::size_t N>
struct array_to_pointer_decay<T[N]>
{
typedef const T * type;
};
template<typename Target, typename Source>
Target my_cast_internal(const Source& s)
{
return boost::lexical_cast<Target>(s);
}
template<>
inline bool my_cast_internal(const std::string& src)
{
return str_to_bool(src);
}
template<>
inline bool my_cast_internal(const char* const& src)
{
return str_to_bool(src);
}
template<typename Target, typename Source>
inline Target my_cast(const Source& s)
{
typedef typename array_to_pointer_decay<Source>::type src;
return my_cast_internal<Target, src>(s);
}
The main challenge is to deal with array types. The array_to_pointer_decay converts any array type to the corresponding pointer type. The rest is easy now.
You need to take a const char*, not a const char*&. The mutable lvalue reference here will only bind to an lvalue, whereas the decay from the array type that the string literal actually is will only produce an rvalue const char*, to which you can only bind a const reference.
Let me add this as a new answer... a type-erasing version!
For C++98/03
/* Core caster */
bool str_to_bool(const std::string &str)
{
if(str == "1" || str == "true" || str == "TRUE")
return true;
else if(str == "0" || str == "false" || str == "FALSE")
return false;
else
throw std::runtime_error("Bad cast from std::string to bool!");
}
/* Type erasing scaffold */
struct TypeEraseBase
{
virtual bool cast() const = 0;
virtual ~TypeEraseBase() { }
};
template <typename T>
struct TypeEraseImpl : public TypeEraseBase
{
TypeEraseImpl(const T & tt) : t(tt) { }
virtual bool cast() const { return boost::lexical_cast<T>(t); }
private:
const T & t;
};
/* Specializations go here */
template <>
struct TypeEraseImpl<std::string> : public TypeEraseBase
{
TypeEraseImpl(const std::string & tt) : t(tt) { }
virtual bool cast() const { return str_to_bool(t); }
private:
const std::string & t;
};
template <size_t N>
struct TypeEraseImpl<char[N]> : public TypeEraseBase
{
TypeEraseImpl(const char (& tt)[N]) : t(tt) { }
virtual bool cast() const { return str_to_bool(std::string(t)); }
private:
const char (& t)[N];
};
template <>
struct TypeEraseImpl<const char *> : public TypeEraseBase
{
TypeEraseImpl(const char * const & tt) : t(tt) { }
virtual bool cast() const { return str_to_bool(std::string(t)); }
private:
const char * const & t;
};
/* User interface class */
struct my_cast
{
template <typename T> my_cast(const T & tt)
: pt(new TypeEraseImpl<T>(tt))
{
}
~my_cast() { if (pt) delete pt; }
inline bool cast() const { return pt->cast(); }
private:
const TypeEraseBase * const pt;
};
// Usage example
int main()
{
const char * const q = "true";
std::cout << my_cast(1).cast() << std::endl;
std::cout << my_cast(std::string("true")).cast() << std::endl;
std::cout << my_cast("true").cast() << std::endl;
std::cout << my_cast(q).cast() << std::endl;
return 0;
}
Type-traited version, templated return type
#include <string>
#include <stdexcept>
#include <iostream>
#include <ostream>
#include <boost/lexical_cast.hpp>
template <typename T> struct is_string : std::false_type { };
template <> struct is_string<std::string> : std::true_type { };
template <> struct is_string<const char *> : std::true_type { };
template <std::size_t N> struct is_string<char[N]> : std::true_type { };
/* The actual caster class */
template <typename T, bool B> struct to_bool
{
static inline bool cast(const T & t)
{
return boost::lexical_cast<T>(t);
}
};
template <typename T> struct to_bool<T, true>
{
static inline bool cast(const T & t)
{
const std::string str(t);
if(str == "1" || str == "true" || str == "TRUE")
return true;
else if(str == "0" || str == "false" || str == "FALSE")
return false;
else
throw std::runtime_error("Bad cast from std::string to bool!");
}
};
/* Type erasing helper class */
template <typename Target>
struct TypeEraseBase
{
virtual Target cast() const = 0;
virtual ~TypeEraseBase() { }
};
template <typename T, typename Target>
struct TypeEraseImpl : public TypeEraseBase<Target>
{
TypeEraseImpl(const T & tt) : t(tt) { }
virtual Target cast() const { return boost::lexical_cast<T>(t); }
private:
const T & t;
};
template <typename T>
struct TypeEraseImpl<T, bool> : public TypeEraseBase<bool>
{
TypeEraseImpl(const T & tt) : t(tt) { }
virtual bool cast() const { return to_bool<T, is_string<T>::value>::cast(t); }
private:
const T & t;
};
/* User interface class */
template <typename Target>
struct my_cast
{
template <typename T> my_cast(const T & tt)
: pt(new TypeEraseImpl<T, Target>(tt)) { }
~my_cast() { if (pt) delete pt; }
inline Target cast() const { return pt->cast(); }
private:
const TypeEraseBase<Target> * const pt;
};
template <typename Target>
std::ostream & operator<<(std::ostream & stream, const my_cast<Target> & c)
{ return stream << c.cast(); }
/* Usage */
int main()
{
const char * const q = "true";
std::cout << my_cast<bool>(1) << std::endl;
std::cout << my_cast<bool>(std::string("true")) << std::endl;
std::cout << my_cast<bool>("true") << std::endl;
std::cout << my_cast<bool>(q) << std::endl;
return 0;
}

Dynamic compile time mixins

I'm trying to come up with a way to define dynamic mixins at compile time. I currently have a very hacky solution that only partially does what I want, but I'm not sure how to improve it.
I'm aware of some more C++ like solutions using typelist's, but they require all of the types to be defined statically which I'm trying to avoid.
This is mostly just a thought exercise to learn C++ better, and I'm sure that my current implementation is not very good C++. Any suggestions for improvements or different ideas to try would be welcome.
The main problems with my current implementation are:
Each mixin class is only aware of itself and classes lower then itself in the hierarchy. I'd like each mixin class to be able to return a new mixin with a different underlying type. In the example code below I'd like PrintOnce to be able to have a method which returns a PrintTwice<PrintOnce<Printer<int > > > object.
Any usage of this idea would need to have an order of header inclusion. All the boiler plate code in the beginning would need to be in one header, then all of the mixin classes would need to be defined, and finally the make_mixed function could be defined. Currently any mixin defined after the make_mixed function is ignored.
The macro's and general hackyness of the implementation.
I apologize for the length, but this is the most simplified example I could come up with.
Thanks for any help.
#include <string>
#include <vector>
#include <iostream>
using namespace std;
template<class Underlying>
struct Printer
{
Printer(const Underlying &val) : val_(val) {}
Underlying get_val() { return val_; }
private:
Underlying val_;
};
#define CURRENT_NUMBER_MIXED_IN_CLASSES() \
MixinCount<0, __LINE__>::value
#define INCREMENT_MIXIN_CLASS_COUNTER() \
template<int id> \
struct MixinClassCounter< CURRENT_NUMBER_MIXED_IN_CLASSES(), id> \
{ \
static const bool is_defined = true; \
}
template< bool b, typename i, typename j >
struct select_value;
template<class i, class j>
struct select_value<true, i, j>
{
static const int value = i::value;
};
template<class i, class j>
struct select_value<false, i, j>
{
static const int value = j::value;
};
template<int i>
struct IntToVal
{
static const int value = i;
};
namespace
{
template<int count, int id>
struct MixinClassCounter
{
static const bool is_defined = false;
};
template<int count, int id>
struct MixinCount
{
static const int value = select_value<MixinClassCounter<count, id>::is_defined,
MixinCount<count + 1, id>,
IntToVal<count> >::value;
};
template<class Underlying, int i>
struct MixinBuilder {};
template<class Underlying>
struct MixinBuilder<Underlying, 0>
{
typedef Printer<Underlying> type;
};
INCREMENT_MIXIN_CLASS_COUNTER();
}
#define DECLARE_MIXIN_BEGIN(name) \
template<class Base> \
struct name : Base \
{ \
template<class Underlying> \
name(const Underlying &val) : Base(val) {}
#define DECLARE_MIXIN_END(name) \
}; \
namespace \
{ \
template<class Underlying> \
struct MixinBuilder<Underlying, CURRENT_NUMBER_MIXED_IN_CLASSES()> \
{ \
typedef name< typename MixinBuilder<Underlying, CURRENT_NUMBER_MIXED_IN_CLASSES() - 1>::type > type; \
}; \
INCREMENT_MIXIN_CLASS_COUNTER(); \
} \
DECLARE_MIXIN_BEGIN(PrintOnce)
void print_once()
{
cout << Base::get_val() << endl;
}
DECLARE_MIXIN_END(PrintOnce)
DECLARE_MIXIN_BEGIN(PrintTwice)
void print_twice()
{
cout << Base::get_val() << endl;
cout << Base::get_val() << endl;
}
DECLARE_MIXIN_END(PrintTwice)
template<class T>
typename MixinBuilder<T, CURRENT_NUMBER_MIXED_IN_CLASSES() - 1>::type make_mixed(const T &val)
{
return typename MixinBuilder<T, CURRENT_NUMBER_MIXED_IN_CLASSES() - 1>::type(val);
}
int main()
{
string test("this is a test");
auto printable_string = make_mixed(test);
printable_string.print_once();
printable_string.print_twice();
}
Here's a cleaner solution without macros:
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::string;
template <typename T>
struct RefWrapper
{
T *self;
RefWrapper () : self (nullptr) {abort ();} // should never be called
RefWrapper (T &self) : self (&self) {}
};
template <typename T>
struct PrintOnce : virtual RefWrapper<T>
{
PrintOnce () {} // workaround gcc 4.6 bug
void print_once () {cout << *RefWrapper<T>::self << endl;}
};
template <typename T>
struct PrintTwice : virtual RefWrapper<T>
{
PrintTwice () {} // workaround gcc 4.6 bug
void print_twice ()
{
cout << *RefWrapper<T>::self << endl;
cout << *RefWrapper<T>::self << endl;
}
};
template <typename T, typename... Args>
struct Mixed : Args...
{
Mixed (T &self) :
RefWrapper<T> (self),
Args ()... {}
Mixed (const Mixed &copy) :
RefWrapper<T> (*copy.self),
Args ()... {}
};
template <template <typename U> class Mixin, typename T>
Mixed<T, Mixin<T> > add_mixin (T &original)
{
return Mixed<T, Mixin<T> > (original);
}
template <template <typename U> class Mixin, typename T,
typename... OtherMixins>
Mixed<T, OtherMixins..., Mixin<T> >
add_mixin (Mixed<T, OtherMixins...> &original)
{
return Mixed<T, OtherMixins..., Mixin<T> > (*original.self);
}
int main ()
{
string foo = "test";
auto p1 = add_mixin<PrintOnce> (foo);
p1.print_once ();
auto p2 = add_mixin<PrintTwice> (p1);
p2.print_once ();
p2.print_twice ();
}
Unfortunately, it still doesn't accomplish your requirement of having each mixin class being aware of all other mixin classes. I'm not sure if that's even possible at compile-time, though.