Meta Mixin.. is that even a thing? (Template Meta-Programming)












0















I want to present a "pattern of mixin based structure"(is this even a term?) but not quite sure if it would hold up in "some situation".
Basic idea is to generate "type using template class" that multiply inherit mixins. So the type declaration would look like: typedef BaseType<Mixin1, Mixin2, MixinN> Type1;
Some accomplishments by the approach:





  • Type1's special feature like operator overloads and Constructor overloads are always available.

  • Explicit type casting overhead is abstracted away by BaseType.

  • C++ multiple implicit conversion barrier is not a problem.


Usual template mixin approach form here looks like: template<class Base> class Printing : public Base {...}. Main drawback for me with this approach:




  • It is necessary to explicitly cast Printing to Base to use some of Base's special features, Or have to provide those overloads explicitly (I know it would just be a matter of one line of codes). But in some situation it would be irritating.


That is why I have come up with the idea to generate the base.
Please take a look at the implementation ("some situation"):



#include <iostream>
#include <functional>

#ifdef QT_CORE_LIB
#include <QString>
#endif


template<template<class> class... mixin_t>
class StringType : public mixin_t<StringType<mixin_t...>>...
{
std::string _value;

public:
StringType() : _value("") {}

StringType(const StringType &other) = default; // Copy

StringType(StringType &&other) = default; // Move

#ifdef QT_CORE_LIB
StringType(const QString &value) { this->_value = value.toStdString(); }
#endif

StringType(const std::string &value) { _value = value; }

StringType(const char *value) { _value = value; }

template<template<class> class T>
StringType(const StringType<T> &value)
{
_value = static_cast<const std::string &>(value);
}


StringType &operator=(const StringType &rhs) = default; // copy assign
StringType &operator=(StringType &&rhs) = default; // Move assign


#ifdef QT_CORE_LIB
operator QString() const { return QString::fromStdString(_value);}
#endif

operator std::string() const { return _value; }

operator const char *() const{ return _value.c_str(); }
};




template<class this_t> struct _empty_mixn {};

template<class this_t> struct ToStringMixin
{
this_t toString() const { return *static_cast<const this_t *>(this); }
};

template<class this_t> struct StringPrinterMixin
{
void print() const
{
std::cout << "From the printer: " << *static_cast<const this_t *>(this);
}
};




typedef StringType<_empty_mixn> String;
typedef StringType<ToStringMixin> Message;
typedef StringType<ToStringMixin, StringPrinterMixin> PrinterAttachedString;




int main()
{
Message msg1(String("msg1n"));
std::cout << msg1;
std::cout << "toString() : " << msg1.toString();

Message msg2 = String("msg2n");
std::cout << msg2;
std::cout << "toString() : " << msg2.toString();

Message msg3(std::string("msg3n"));
std::cout << msg3;
std::cout << "toString() : " << msg3.toString();

Message msg4 = std::string("msg4n");
std::cout << msg4;
std::cout << "toString() : " << msg4.toString();

Message msg5("msg5n");
std::cout << msg5;
std::cout << "toString() : " << msg5.toString();

Message msg6 = "msg6n";
std::cout << msg6;
std::cout << "toString() : " << msg6.toString();

std::cout << "n---------------------nn";

PrinterAttachedString str1(String("str1n"));
std::cout << str1;
std::cout << "toString() : " << str1.toString();
str1.print();

PrinterAttachedString str2 = String("str2n");
std::cout << str2;
std::cout << "toString() : " << str2.toString();
str2.print();

PrinterAttachedString str3(std::string("str3n"));
std::cout << str3;
std::cout << "toString() : " << str3.toString();
str3.print();

PrinterAttachedString str4 = std::string("str4n");
std::cout << str4;
std::cout << "toString() : " << str4.toString();
str4.print();

PrinterAttachedString str5("str5n");
std::cout << str5;
std::cout << "toString() : " << str5.toString();
str5.print();

PrinterAttachedString str6 = "str6n";
std::cout << str6;
std::cout << "toString() : " << str6.toString();
str6.print();

return 0;
}


So, my questions:




  • Would it be practical use this in a situation where operator overloading/implicit casting feature necessary?

  • Does it seem, there would be a necessity of virtual inheritance?

  • Are there any other implementation like this (My search was a failure)?

  • Finally, is there a thing called "meta mixin" that would provide a type's special features?


Edit: In response to Phil1970's answer:



I am going to start with the answer to the question 3.




  • This approach leads to class proliferation: I totally agree. One big drawback I have to admit.

  • Increases coupling. Not sure how it increases coupling. *1

  • The rests marked there, I believe is not applicable due to the fact that StringType is quite final. And StringType does not know or about mixed class for real. *1


Now for the answer to the question no 1.




  • It is usually best to avoid implicit conversion.

  • The rests to me is ok as long as it is final. *2


With previous question gone (huge thanks to Phil) arose new questions.




  • *1: It is just one header-only, StringStyle does not depend on mixins and I see no reason to be so. And certainly this it can use private header if somehow becomes necessary. Then how it enforcing coupling?

  • *2: Just looking for opinions or to get me corrected.


Thanks a lot.










share|improve this question

























  • I would say it is the wrong approach… Use a namespace with free function or if the code is more complex, use an helper class. For example: namespace Printer { void print(const string &s) { std::cout << "From the printer: " << s; } }

    – Phil1970
    Nov 16 '18 at 1:18













  • @Phil1970 print() or toString() is rally not my concern. Please see in my code that operator overloading (assignment & casting) and constructor conversion is the main feature here since it wraps different string implementation. Will be very glad if reconsider to check again my approach. Thanks.

    – Shabbir Ahmed
    Nov 16 '18 at 1:41






  • 1





    Well your implementation forces UB. So that is bad.

    – Yakk - Adam Nevraumont
    Nov 16 '18 at 1:58











  • Fix; mixin_t<StringType<mixin_t...>>...

    – Yakk - Adam Nevraumont
    Nov 16 '18 at 2:09






  • 1





    @shabb CRTP is unsafe and unchecked.

    – Yakk - Adam Nevraumont
    Nov 16 '18 at 3:04
















0















I want to present a "pattern of mixin based structure"(is this even a term?) but not quite sure if it would hold up in "some situation".
Basic idea is to generate "type using template class" that multiply inherit mixins. So the type declaration would look like: typedef BaseType<Mixin1, Mixin2, MixinN> Type1;
Some accomplishments by the approach:





  • Type1's special feature like operator overloads and Constructor overloads are always available.

  • Explicit type casting overhead is abstracted away by BaseType.

  • C++ multiple implicit conversion barrier is not a problem.


Usual template mixin approach form here looks like: template<class Base> class Printing : public Base {...}. Main drawback for me with this approach:




  • It is necessary to explicitly cast Printing to Base to use some of Base's special features, Or have to provide those overloads explicitly (I know it would just be a matter of one line of codes). But in some situation it would be irritating.


That is why I have come up with the idea to generate the base.
Please take a look at the implementation ("some situation"):



#include <iostream>
#include <functional>

#ifdef QT_CORE_LIB
#include <QString>
#endif


template<template<class> class... mixin_t>
class StringType : public mixin_t<StringType<mixin_t...>>...
{
std::string _value;

public:
StringType() : _value("") {}

StringType(const StringType &other) = default; // Copy

StringType(StringType &&other) = default; // Move

#ifdef QT_CORE_LIB
StringType(const QString &value) { this->_value = value.toStdString(); }
#endif

StringType(const std::string &value) { _value = value; }

StringType(const char *value) { _value = value; }

template<template<class> class T>
StringType(const StringType<T> &value)
{
_value = static_cast<const std::string &>(value);
}


StringType &operator=(const StringType &rhs) = default; // copy assign
StringType &operator=(StringType &&rhs) = default; // Move assign


#ifdef QT_CORE_LIB
operator QString() const { return QString::fromStdString(_value);}
#endif

operator std::string() const { return _value; }

operator const char *() const{ return _value.c_str(); }
};




template<class this_t> struct _empty_mixn {};

template<class this_t> struct ToStringMixin
{
this_t toString() const { return *static_cast<const this_t *>(this); }
};

template<class this_t> struct StringPrinterMixin
{
void print() const
{
std::cout << "From the printer: " << *static_cast<const this_t *>(this);
}
};




typedef StringType<_empty_mixn> String;
typedef StringType<ToStringMixin> Message;
typedef StringType<ToStringMixin, StringPrinterMixin> PrinterAttachedString;




int main()
{
Message msg1(String("msg1n"));
std::cout << msg1;
std::cout << "toString() : " << msg1.toString();

Message msg2 = String("msg2n");
std::cout << msg2;
std::cout << "toString() : " << msg2.toString();

Message msg3(std::string("msg3n"));
std::cout << msg3;
std::cout << "toString() : " << msg3.toString();

Message msg4 = std::string("msg4n");
std::cout << msg4;
std::cout << "toString() : " << msg4.toString();

Message msg5("msg5n");
std::cout << msg5;
std::cout << "toString() : " << msg5.toString();

Message msg6 = "msg6n";
std::cout << msg6;
std::cout << "toString() : " << msg6.toString();

std::cout << "n---------------------nn";

PrinterAttachedString str1(String("str1n"));
std::cout << str1;
std::cout << "toString() : " << str1.toString();
str1.print();

PrinterAttachedString str2 = String("str2n");
std::cout << str2;
std::cout << "toString() : " << str2.toString();
str2.print();

PrinterAttachedString str3(std::string("str3n"));
std::cout << str3;
std::cout << "toString() : " << str3.toString();
str3.print();

PrinterAttachedString str4 = std::string("str4n");
std::cout << str4;
std::cout << "toString() : " << str4.toString();
str4.print();

PrinterAttachedString str5("str5n");
std::cout << str5;
std::cout << "toString() : " << str5.toString();
str5.print();

PrinterAttachedString str6 = "str6n";
std::cout << str6;
std::cout << "toString() : " << str6.toString();
str6.print();

return 0;
}


So, my questions:




  • Would it be practical use this in a situation where operator overloading/implicit casting feature necessary?

  • Does it seem, there would be a necessity of virtual inheritance?

  • Are there any other implementation like this (My search was a failure)?

  • Finally, is there a thing called "meta mixin" that would provide a type's special features?


Edit: In response to Phil1970's answer:



I am going to start with the answer to the question 3.




  • This approach leads to class proliferation: I totally agree. One big drawback I have to admit.

  • Increases coupling. Not sure how it increases coupling. *1

  • The rests marked there, I believe is not applicable due to the fact that StringType is quite final. And StringType does not know or about mixed class for real. *1


Now for the answer to the question no 1.




  • It is usually best to avoid implicit conversion.

  • The rests to me is ok as long as it is final. *2


With previous question gone (huge thanks to Phil) arose new questions.




  • *1: It is just one header-only, StringStyle does not depend on mixins and I see no reason to be so. And certainly this it can use private header if somehow becomes necessary. Then how it enforcing coupling?

  • *2: Just looking for opinions or to get me corrected.


Thanks a lot.










share|improve this question

























  • I would say it is the wrong approach… Use a namespace with free function or if the code is more complex, use an helper class. For example: namespace Printer { void print(const string &s) { std::cout << "From the printer: " << s; } }

    – Phil1970
    Nov 16 '18 at 1:18













  • @Phil1970 print() or toString() is rally not my concern. Please see in my code that operator overloading (assignment & casting) and constructor conversion is the main feature here since it wraps different string implementation. Will be very glad if reconsider to check again my approach. Thanks.

    – Shabbir Ahmed
    Nov 16 '18 at 1:41






  • 1





    Well your implementation forces UB. So that is bad.

    – Yakk - Adam Nevraumont
    Nov 16 '18 at 1:58











  • Fix; mixin_t<StringType<mixin_t...>>...

    – Yakk - Adam Nevraumont
    Nov 16 '18 at 2:09






  • 1





    @shabb CRTP is unsafe and unchecked.

    – Yakk - Adam Nevraumont
    Nov 16 '18 at 3:04














0












0








0








I want to present a "pattern of mixin based structure"(is this even a term?) but not quite sure if it would hold up in "some situation".
Basic idea is to generate "type using template class" that multiply inherit mixins. So the type declaration would look like: typedef BaseType<Mixin1, Mixin2, MixinN> Type1;
Some accomplishments by the approach:





  • Type1's special feature like operator overloads and Constructor overloads are always available.

  • Explicit type casting overhead is abstracted away by BaseType.

  • C++ multiple implicit conversion barrier is not a problem.


Usual template mixin approach form here looks like: template<class Base> class Printing : public Base {...}. Main drawback for me with this approach:




  • It is necessary to explicitly cast Printing to Base to use some of Base's special features, Or have to provide those overloads explicitly (I know it would just be a matter of one line of codes). But in some situation it would be irritating.


That is why I have come up with the idea to generate the base.
Please take a look at the implementation ("some situation"):



#include <iostream>
#include <functional>

#ifdef QT_CORE_LIB
#include <QString>
#endif


template<template<class> class... mixin_t>
class StringType : public mixin_t<StringType<mixin_t...>>...
{
std::string _value;

public:
StringType() : _value("") {}

StringType(const StringType &other) = default; // Copy

StringType(StringType &&other) = default; // Move

#ifdef QT_CORE_LIB
StringType(const QString &value) { this->_value = value.toStdString(); }
#endif

StringType(const std::string &value) { _value = value; }

StringType(const char *value) { _value = value; }

template<template<class> class T>
StringType(const StringType<T> &value)
{
_value = static_cast<const std::string &>(value);
}


StringType &operator=(const StringType &rhs) = default; // copy assign
StringType &operator=(StringType &&rhs) = default; // Move assign


#ifdef QT_CORE_LIB
operator QString() const { return QString::fromStdString(_value);}
#endif

operator std::string() const { return _value; }

operator const char *() const{ return _value.c_str(); }
};




template<class this_t> struct _empty_mixn {};

template<class this_t> struct ToStringMixin
{
this_t toString() const { return *static_cast<const this_t *>(this); }
};

template<class this_t> struct StringPrinterMixin
{
void print() const
{
std::cout << "From the printer: " << *static_cast<const this_t *>(this);
}
};




typedef StringType<_empty_mixn> String;
typedef StringType<ToStringMixin> Message;
typedef StringType<ToStringMixin, StringPrinterMixin> PrinterAttachedString;




int main()
{
Message msg1(String("msg1n"));
std::cout << msg1;
std::cout << "toString() : " << msg1.toString();

Message msg2 = String("msg2n");
std::cout << msg2;
std::cout << "toString() : " << msg2.toString();

Message msg3(std::string("msg3n"));
std::cout << msg3;
std::cout << "toString() : " << msg3.toString();

Message msg4 = std::string("msg4n");
std::cout << msg4;
std::cout << "toString() : " << msg4.toString();

Message msg5("msg5n");
std::cout << msg5;
std::cout << "toString() : " << msg5.toString();

Message msg6 = "msg6n";
std::cout << msg6;
std::cout << "toString() : " << msg6.toString();

std::cout << "n---------------------nn";

PrinterAttachedString str1(String("str1n"));
std::cout << str1;
std::cout << "toString() : " << str1.toString();
str1.print();

PrinterAttachedString str2 = String("str2n");
std::cout << str2;
std::cout << "toString() : " << str2.toString();
str2.print();

PrinterAttachedString str3(std::string("str3n"));
std::cout << str3;
std::cout << "toString() : " << str3.toString();
str3.print();

PrinterAttachedString str4 = std::string("str4n");
std::cout << str4;
std::cout << "toString() : " << str4.toString();
str4.print();

PrinterAttachedString str5("str5n");
std::cout << str5;
std::cout << "toString() : " << str5.toString();
str5.print();

PrinterAttachedString str6 = "str6n";
std::cout << str6;
std::cout << "toString() : " << str6.toString();
str6.print();

return 0;
}


So, my questions:




  • Would it be practical use this in a situation where operator overloading/implicit casting feature necessary?

  • Does it seem, there would be a necessity of virtual inheritance?

  • Are there any other implementation like this (My search was a failure)?

  • Finally, is there a thing called "meta mixin" that would provide a type's special features?


Edit: In response to Phil1970's answer:



I am going to start with the answer to the question 3.




  • This approach leads to class proliferation: I totally agree. One big drawback I have to admit.

  • Increases coupling. Not sure how it increases coupling. *1

  • The rests marked there, I believe is not applicable due to the fact that StringType is quite final. And StringType does not know or about mixed class for real. *1


Now for the answer to the question no 1.




  • It is usually best to avoid implicit conversion.

  • The rests to me is ok as long as it is final. *2


With previous question gone (huge thanks to Phil) arose new questions.




  • *1: It is just one header-only, StringStyle does not depend on mixins and I see no reason to be so. And certainly this it can use private header if somehow becomes necessary. Then how it enforcing coupling?

  • *2: Just looking for opinions or to get me corrected.


Thanks a lot.










share|improve this question
















I want to present a "pattern of mixin based structure"(is this even a term?) but not quite sure if it would hold up in "some situation".
Basic idea is to generate "type using template class" that multiply inherit mixins. So the type declaration would look like: typedef BaseType<Mixin1, Mixin2, MixinN> Type1;
Some accomplishments by the approach:





  • Type1's special feature like operator overloads and Constructor overloads are always available.

  • Explicit type casting overhead is abstracted away by BaseType.

  • C++ multiple implicit conversion barrier is not a problem.


Usual template mixin approach form here looks like: template<class Base> class Printing : public Base {...}. Main drawback for me with this approach:




  • It is necessary to explicitly cast Printing to Base to use some of Base's special features, Or have to provide those overloads explicitly (I know it would just be a matter of one line of codes). But in some situation it would be irritating.


That is why I have come up with the idea to generate the base.
Please take a look at the implementation ("some situation"):



#include <iostream>
#include <functional>

#ifdef QT_CORE_LIB
#include <QString>
#endif


template<template<class> class... mixin_t>
class StringType : public mixin_t<StringType<mixin_t...>>...
{
std::string _value;

public:
StringType() : _value("") {}

StringType(const StringType &other) = default; // Copy

StringType(StringType &&other) = default; // Move

#ifdef QT_CORE_LIB
StringType(const QString &value) { this->_value = value.toStdString(); }
#endif

StringType(const std::string &value) { _value = value; }

StringType(const char *value) { _value = value; }

template<template<class> class T>
StringType(const StringType<T> &value)
{
_value = static_cast<const std::string &>(value);
}


StringType &operator=(const StringType &rhs) = default; // copy assign
StringType &operator=(StringType &&rhs) = default; // Move assign


#ifdef QT_CORE_LIB
operator QString() const { return QString::fromStdString(_value);}
#endif

operator std::string() const { return _value; }

operator const char *() const{ return _value.c_str(); }
};




template<class this_t> struct _empty_mixn {};

template<class this_t> struct ToStringMixin
{
this_t toString() const { return *static_cast<const this_t *>(this); }
};

template<class this_t> struct StringPrinterMixin
{
void print() const
{
std::cout << "From the printer: " << *static_cast<const this_t *>(this);
}
};




typedef StringType<_empty_mixn> String;
typedef StringType<ToStringMixin> Message;
typedef StringType<ToStringMixin, StringPrinterMixin> PrinterAttachedString;




int main()
{
Message msg1(String("msg1n"));
std::cout << msg1;
std::cout << "toString() : " << msg1.toString();

Message msg2 = String("msg2n");
std::cout << msg2;
std::cout << "toString() : " << msg2.toString();

Message msg3(std::string("msg3n"));
std::cout << msg3;
std::cout << "toString() : " << msg3.toString();

Message msg4 = std::string("msg4n");
std::cout << msg4;
std::cout << "toString() : " << msg4.toString();

Message msg5("msg5n");
std::cout << msg5;
std::cout << "toString() : " << msg5.toString();

Message msg6 = "msg6n";
std::cout << msg6;
std::cout << "toString() : " << msg6.toString();

std::cout << "n---------------------nn";

PrinterAttachedString str1(String("str1n"));
std::cout << str1;
std::cout << "toString() : " << str1.toString();
str1.print();

PrinterAttachedString str2 = String("str2n");
std::cout << str2;
std::cout << "toString() : " << str2.toString();
str2.print();

PrinterAttachedString str3(std::string("str3n"));
std::cout << str3;
std::cout << "toString() : " << str3.toString();
str3.print();

PrinterAttachedString str4 = std::string("str4n");
std::cout << str4;
std::cout << "toString() : " << str4.toString();
str4.print();

PrinterAttachedString str5("str5n");
std::cout << str5;
std::cout << "toString() : " << str5.toString();
str5.print();

PrinterAttachedString str6 = "str6n";
std::cout << str6;
std::cout << "toString() : " << str6.toString();
str6.print();

return 0;
}


So, my questions:




  • Would it be practical use this in a situation where operator overloading/implicit casting feature necessary?

  • Does it seem, there would be a necessity of virtual inheritance?

  • Are there any other implementation like this (My search was a failure)?

  • Finally, is there a thing called "meta mixin" that would provide a type's special features?


Edit: In response to Phil1970's answer:



I am going to start with the answer to the question 3.




  • This approach leads to class proliferation: I totally agree. One big drawback I have to admit.

  • Increases coupling. Not sure how it increases coupling. *1

  • The rests marked there, I believe is not applicable due to the fact that StringType is quite final. And StringType does not know or about mixed class for real. *1


Now for the answer to the question no 1.




  • It is usually best to avoid implicit conversion.

  • The rests to me is ok as long as it is final. *2


With previous question gone (huge thanks to Phil) arose new questions.




  • *1: It is just one header-only, StringStyle does not depend on mixins and I see no reason to be so. And certainly this it can use private header if somehow becomes necessary. Then how it enforcing coupling?

  • *2: Just looking for opinions or to get me corrected.


Thanks a lot.







c++ c++11 mixins template-meta-programming crtp






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 16 '18 at 7:04







Shabbir Ahmed

















asked Nov 16 '18 at 0:43









Shabbir AhmedShabbir Ahmed

62




62













  • I would say it is the wrong approach… Use a namespace with free function or if the code is more complex, use an helper class. For example: namespace Printer { void print(const string &s) { std::cout << "From the printer: " << s; } }

    – Phil1970
    Nov 16 '18 at 1:18













  • @Phil1970 print() or toString() is rally not my concern. Please see in my code that operator overloading (assignment & casting) and constructor conversion is the main feature here since it wraps different string implementation. Will be very glad if reconsider to check again my approach. Thanks.

    – Shabbir Ahmed
    Nov 16 '18 at 1:41






  • 1





    Well your implementation forces UB. So that is bad.

    – Yakk - Adam Nevraumont
    Nov 16 '18 at 1:58











  • Fix; mixin_t<StringType<mixin_t...>>...

    – Yakk - Adam Nevraumont
    Nov 16 '18 at 2:09






  • 1





    @shabb CRTP is unsafe and unchecked.

    – Yakk - Adam Nevraumont
    Nov 16 '18 at 3:04



















  • I would say it is the wrong approach… Use a namespace with free function or if the code is more complex, use an helper class. For example: namespace Printer { void print(const string &s) { std::cout << "From the printer: " << s; } }

    – Phil1970
    Nov 16 '18 at 1:18













  • @Phil1970 print() or toString() is rally not my concern. Please see in my code that operator overloading (assignment & casting) and constructor conversion is the main feature here since it wraps different string implementation. Will be very glad if reconsider to check again my approach. Thanks.

    – Shabbir Ahmed
    Nov 16 '18 at 1:41






  • 1





    Well your implementation forces UB. So that is bad.

    – Yakk - Adam Nevraumont
    Nov 16 '18 at 1:58











  • Fix; mixin_t<StringType<mixin_t...>>...

    – Yakk - Adam Nevraumont
    Nov 16 '18 at 2:09






  • 1





    @shabb CRTP is unsafe and unchecked.

    – Yakk - Adam Nevraumont
    Nov 16 '18 at 3:04

















I would say it is the wrong approach… Use a namespace with free function or if the code is more complex, use an helper class. For example: namespace Printer { void print(const string &s) { std::cout << "From the printer: " << s; } }

– Phil1970
Nov 16 '18 at 1:18







I would say it is the wrong approach… Use a namespace with free function or if the code is more complex, use an helper class. For example: namespace Printer { void print(const string &s) { std::cout << "From the printer: " << s; } }

– Phil1970
Nov 16 '18 at 1:18















@Phil1970 print() or toString() is rally not my concern. Please see in my code that operator overloading (assignment & casting) and constructor conversion is the main feature here since it wraps different string implementation. Will be very glad if reconsider to check again my approach. Thanks.

– Shabbir Ahmed
Nov 16 '18 at 1:41





@Phil1970 print() or toString() is rally not my concern. Please see in my code that operator overloading (assignment & casting) and constructor conversion is the main feature here since it wraps different string implementation. Will be very glad if reconsider to check again my approach. Thanks.

– Shabbir Ahmed
Nov 16 '18 at 1:41




1




1





Well your implementation forces UB. So that is bad.

– Yakk - Adam Nevraumont
Nov 16 '18 at 1:58





Well your implementation forces UB. So that is bad.

– Yakk - Adam Nevraumont
Nov 16 '18 at 1:58













Fix; mixin_t<StringType<mixin_t...>>...

– Yakk - Adam Nevraumont
Nov 16 '18 at 2:09





Fix; mixin_t<StringType<mixin_t...>>...

– Yakk - Adam Nevraumont
Nov 16 '18 at 2:09




1




1





@shabb CRTP is unsafe and unchecked.

– Yakk - Adam Nevraumont
Nov 16 '18 at 3:04





@shabb CRTP is unsafe and unchecked.

– Yakk - Adam Nevraumont
Nov 16 '18 at 3:04












1 Answer
1






active

oldest

votes


















-1














For your question:




  • It is usually best to avoid implicit conversion. Also you won't be able to reuse std::string operators like +, += with that kind of approach without adding a lot one line function. The wrapper class bring you nothing except adding more conversions as you would then use you new string type and with the mixin approach, this is even worst as you need to also convert between your own types.

  • Why would you use virtual inheritance? Do you really want to derive from multiple classes that have a common base and that have their own data.

  • As this is a bad design, you probably won't find many people doing it. Your design increase coupling, lead to class proliferation, increase type conversions and make maintenance harder among other things.

  • I believe, there is no such thing.


For simple functions like those above, the preferred approach would be to define a namespace (or many if you have a lot of functions that could somehow be categorized like maybe file name manipulation) and then have free functions inside it.



By using a namespace, you have a few advantages:




  • If you call a lot of functions, you can always add an using statement inside your function or source file (never in a header file).

  • Auto suggestion will work well to find those function.


If some of the original mixin maintain state, then you should do an helper class. This could be the case for a class like an HTML builder that might have functions like AddTag, Add Attribute, AddEncodedUrl etc that could be used to create an HTML document.



One big advantage of this approach is that coupling is much looser than in your design. For example, a file pair (header and source) would contains all functions used for the Printer. If you need that, you don't have to create a new class that use some combination of mixin.



One big problem with your approach, is that with time you will have a lot of different StringType<…> If you have 5 mixins that could be used, you have 2^5 = 32 classes. At that point, it is almost sure that you will often need the mixin you didn't include and then you have cascading change if the call it deep. And if you use template everywhere then you will have compilation slowdown and probably some code bloat.



Implicit conversion is also considered to be best avoid in most cases by most experts. If you have multiple conversion from and to many classes, at some point you will have unexpected conversion or ambiguities. Making some conversion explicit can limit the problem. Usually is it best to use explicite conversion as it was done by experts in std::string. You have to call member function c_str() if you want a C style string.



For example, since your StringType class define conversion to both const char * and QString, then if you have a method that accept both (maybe an Append function), then you have a conflict.



If you really want conversion, then use named method instead (for ex. AsQString(), c_str(), tostdstring()...). It help ensure that all conversion are intended. It make it easier to find them and it is certainly better that explicit cast like you have done in a few place in your code. While static_cast and other casts are sometime useful, then can also hide some problem when code is refactored as in some case, the cast might compile while not being correct. This would be the case if you cast to a derived class and at some point decide to change the derived class for something else and forget to update some casts.



You should select the most appropriate string for your application and do conversion when required. In a large application, you might use one type for the UI (ex. CString or QString) while using standard string in librairies that are shared across platforms or with third party library. Some time those libraries have their own string class too. Your selection should try minimize useless conversions.






share|improve this answer
























  • I can't thank you enough for your precious time. If you feel like to spend more time please check my updated questions. Have a nice day.

    – Shabbir Ahmed
    Nov 16 '18 at 7:06











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53329850%2fmeta-mixin-is-that-even-a-thing-template-meta-programming%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









-1














For your question:




  • It is usually best to avoid implicit conversion. Also you won't be able to reuse std::string operators like +, += with that kind of approach without adding a lot one line function. The wrapper class bring you nothing except adding more conversions as you would then use you new string type and with the mixin approach, this is even worst as you need to also convert between your own types.

  • Why would you use virtual inheritance? Do you really want to derive from multiple classes that have a common base and that have their own data.

  • As this is a bad design, you probably won't find many people doing it. Your design increase coupling, lead to class proliferation, increase type conversions and make maintenance harder among other things.

  • I believe, there is no such thing.


For simple functions like those above, the preferred approach would be to define a namespace (or many if you have a lot of functions that could somehow be categorized like maybe file name manipulation) and then have free functions inside it.



By using a namespace, you have a few advantages:




  • If you call a lot of functions, you can always add an using statement inside your function or source file (never in a header file).

  • Auto suggestion will work well to find those function.


If some of the original mixin maintain state, then you should do an helper class. This could be the case for a class like an HTML builder that might have functions like AddTag, Add Attribute, AddEncodedUrl etc that could be used to create an HTML document.



One big advantage of this approach is that coupling is much looser than in your design. For example, a file pair (header and source) would contains all functions used for the Printer. If you need that, you don't have to create a new class that use some combination of mixin.



One big problem with your approach, is that with time you will have a lot of different StringType<…> If you have 5 mixins that could be used, you have 2^5 = 32 classes. At that point, it is almost sure that you will often need the mixin you didn't include and then you have cascading change if the call it deep. And if you use template everywhere then you will have compilation slowdown and probably some code bloat.



Implicit conversion is also considered to be best avoid in most cases by most experts. If you have multiple conversion from and to many classes, at some point you will have unexpected conversion or ambiguities. Making some conversion explicit can limit the problem. Usually is it best to use explicite conversion as it was done by experts in std::string. You have to call member function c_str() if you want a C style string.



For example, since your StringType class define conversion to both const char * and QString, then if you have a method that accept both (maybe an Append function), then you have a conflict.



If you really want conversion, then use named method instead (for ex. AsQString(), c_str(), tostdstring()...). It help ensure that all conversion are intended. It make it easier to find them and it is certainly better that explicit cast like you have done in a few place in your code. While static_cast and other casts are sometime useful, then can also hide some problem when code is refactored as in some case, the cast might compile while not being correct. This would be the case if you cast to a derived class and at some point decide to change the derived class for something else and forget to update some casts.



You should select the most appropriate string for your application and do conversion when required. In a large application, you might use one type for the UI (ex. CString or QString) while using standard string in librairies that are shared across platforms or with third party library. Some time those libraries have their own string class too. Your selection should try minimize useless conversions.






share|improve this answer
























  • I can't thank you enough for your precious time. If you feel like to spend more time please check my updated questions. Have a nice day.

    – Shabbir Ahmed
    Nov 16 '18 at 7:06
















-1














For your question:




  • It is usually best to avoid implicit conversion. Also you won't be able to reuse std::string operators like +, += with that kind of approach without adding a lot one line function. The wrapper class bring you nothing except adding more conversions as you would then use you new string type and with the mixin approach, this is even worst as you need to also convert between your own types.

  • Why would you use virtual inheritance? Do you really want to derive from multiple classes that have a common base and that have their own data.

  • As this is a bad design, you probably won't find many people doing it. Your design increase coupling, lead to class proliferation, increase type conversions and make maintenance harder among other things.

  • I believe, there is no such thing.


For simple functions like those above, the preferred approach would be to define a namespace (or many if you have a lot of functions that could somehow be categorized like maybe file name manipulation) and then have free functions inside it.



By using a namespace, you have a few advantages:




  • If you call a lot of functions, you can always add an using statement inside your function or source file (never in a header file).

  • Auto suggestion will work well to find those function.


If some of the original mixin maintain state, then you should do an helper class. This could be the case for a class like an HTML builder that might have functions like AddTag, Add Attribute, AddEncodedUrl etc that could be used to create an HTML document.



One big advantage of this approach is that coupling is much looser than in your design. For example, a file pair (header and source) would contains all functions used for the Printer. If you need that, you don't have to create a new class that use some combination of mixin.



One big problem with your approach, is that with time you will have a lot of different StringType<…> If you have 5 mixins that could be used, you have 2^5 = 32 classes. At that point, it is almost sure that you will often need the mixin you didn't include and then you have cascading change if the call it deep. And if you use template everywhere then you will have compilation slowdown and probably some code bloat.



Implicit conversion is also considered to be best avoid in most cases by most experts. If you have multiple conversion from and to many classes, at some point you will have unexpected conversion or ambiguities. Making some conversion explicit can limit the problem. Usually is it best to use explicite conversion as it was done by experts in std::string. You have to call member function c_str() if you want a C style string.



For example, since your StringType class define conversion to both const char * and QString, then if you have a method that accept both (maybe an Append function), then you have a conflict.



If you really want conversion, then use named method instead (for ex. AsQString(), c_str(), tostdstring()...). It help ensure that all conversion are intended. It make it easier to find them and it is certainly better that explicit cast like you have done in a few place in your code. While static_cast and other casts are sometime useful, then can also hide some problem when code is refactored as in some case, the cast might compile while not being correct. This would be the case if you cast to a derived class and at some point decide to change the derived class for something else and forget to update some casts.



You should select the most appropriate string for your application and do conversion when required. In a large application, you might use one type for the UI (ex. CString or QString) while using standard string in librairies that are shared across platforms or with third party library. Some time those libraries have their own string class too. Your selection should try minimize useless conversions.






share|improve this answer
























  • I can't thank you enough for your precious time. If you feel like to spend more time please check my updated questions. Have a nice day.

    – Shabbir Ahmed
    Nov 16 '18 at 7:06














-1












-1








-1







For your question:




  • It is usually best to avoid implicit conversion. Also you won't be able to reuse std::string operators like +, += with that kind of approach without adding a lot one line function. The wrapper class bring you nothing except adding more conversions as you would then use you new string type and with the mixin approach, this is even worst as you need to also convert between your own types.

  • Why would you use virtual inheritance? Do you really want to derive from multiple classes that have a common base and that have their own data.

  • As this is a bad design, you probably won't find many people doing it. Your design increase coupling, lead to class proliferation, increase type conversions and make maintenance harder among other things.

  • I believe, there is no such thing.


For simple functions like those above, the preferred approach would be to define a namespace (or many if you have a lot of functions that could somehow be categorized like maybe file name manipulation) and then have free functions inside it.



By using a namespace, you have a few advantages:




  • If you call a lot of functions, you can always add an using statement inside your function or source file (never in a header file).

  • Auto suggestion will work well to find those function.


If some of the original mixin maintain state, then you should do an helper class. This could be the case for a class like an HTML builder that might have functions like AddTag, Add Attribute, AddEncodedUrl etc that could be used to create an HTML document.



One big advantage of this approach is that coupling is much looser than in your design. For example, a file pair (header and source) would contains all functions used for the Printer. If you need that, you don't have to create a new class that use some combination of mixin.



One big problem with your approach, is that with time you will have a lot of different StringType<…> If you have 5 mixins that could be used, you have 2^5 = 32 classes. At that point, it is almost sure that you will often need the mixin you didn't include and then you have cascading change if the call it deep. And if you use template everywhere then you will have compilation slowdown and probably some code bloat.



Implicit conversion is also considered to be best avoid in most cases by most experts. If you have multiple conversion from and to many classes, at some point you will have unexpected conversion or ambiguities. Making some conversion explicit can limit the problem. Usually is it best to use explicite conversion as it was done by experts in std::string. You have to call member function c_str() if you want a C style string.



For example, since your StringType class define conversion to both const char * and QString, then if you have a method that accept both (maybe an Append function), then you have a conflict.



If you really want conversion, then use named method instead (for ex. AsQString(), c_str(), tostdstring()...). It help ensure that all conversion are intended. It make it easier to find them and it is certainly better that explicit cast like you have done in a few place in your code. While static_cast and other casts are sometime useful, then can also hide some problem when code is refactored as in some case, the cast might compile while not being correct. This would be the case if you cast to a derived class and at some point decide to change the derived class for something else and forget to update some casts.



You should select the most appropriate string for your application and do conversion when required. In a large application, you might use one type for the UI (ex. CString or QString) while using standard string in librairies that are shared across platforms or with third party library. Some time those libraries have their own string class too. Your selection should try minimize useless conversions.






share|improve this answer













For your question:




  • It is usually best to avoid implicit conversion. Also you won't be able to reuse std::string operators like +, += with that kind of approach without adding a lot one line function. The wrapper class bring you nothing except adding more conversions as you would then use you new string type and with the mixin approach, this is even worst as you need to also convert between your own types.

  • Why would you use virtual inheritance? Do you really want to derive from multiple classes that have a common base and that have their own data.

  • As this is a bad design, you probably won't find many people doing it. Your design increase coupling, lead to class proliferation, increase type conversions and make maintenance harder among other things.

  • I believe, there is no such thing.


For simple functions like those above, the preferred approach would be to define a namespace (or many if you have a lot of functions that could somehow be categorized like maybe file name manipulation) and then have free functions inside it.



By using a namespace, you have a few advantages:




  • If you call a lot of functions, you can always add an using statement inside your function or source file (never in a header file).

  • Auto suggestion will work well to find those function.


If some of the original mixin maintain state, then you should do an helper class. This could be the case for a class like an HTML builder that might have functions like AddTag, Add Attribute, AddEncodedUrl etc that could be used to create an HTML document.



One big advantage of this approach is that coupling is much looser than in your design. For example, a file pair (header and source) would contains all functions used for the Printer. If you need that, you don't have to create a new class that use some combination of mixin.



One big problem with your approach, is that with time you will have a lot of different StringType<…> If you have 5 mixins that could be used, you have 2^5 = 32 classes. At that point, it is almost sure that you will often need the mixin you didn't include and then you have cascading change if the call it deep. And if you use template everywhere then you will have compilation slowdown and probably some code bloat.



Implicit conversion is also considered to be best avoid in most cases by most experts. If you have multiple conversion from and to many classes, at some point you will have unexpected conversion or ambiguities. Making some conversion explicit can limit the problem. Usually is it best to use explicite conversion as it was done by experts in std::string. You have to call member function c_str() if you want a C style string.



For example, since your StringType class define conversion to both const char * and QString, then if you have a method that accept both (maybe an Append function), then you have a conflict.



If you really want conversion, then use named method instead (for ex. AsQString(), c_str(), tostdstring()...). It help ensure that all conversion are intended. It make it easier to find them and it is certainly better that explicit cast like you have done in a few place in your code. While static_cast and other casts are sometime useful, then can also hide some problem when code is refactored as in some case, the cast might compile while not being correct. This would be the case if you cast to a derived class and at some point decide to change the derived class for something else and forget to update some casts.



You should select the most appropriate string for your application and do conversion when required. In a large application, you might use one type for the UI (ex. CString or QString) while using standard string in librairies that are shared across platforms or with third party library. Some time those libraries have their own string class too. Your selection should try minimize useless conversions.







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 16 '18 at 3:16









Phil1970Phil1970

1,3581810




1,3581810













  • I can't thank you enough for your precious time. If you feel like to spend more time please check my updated questions. Have a nice day.

    – Shabbir Ahmed
    Nov 16 '18 at 7:06



















  • I can't thank you enough for your precious time. If you feel like to spend more time please check my updated questions. Have a nice day.

    – Shabbir Ahmed
    Nov 16 '18 at 7:06

















I can't thank you enough for your precious time. If you feel like to spend more time please check my updated questions. Have a nice day.

– Shabbir Ahmed
Nov 16 '18 at 7:06





I can't thank you enough for your precious time. If you feel like to spend more time please check my updated questions. Have a nice day.

– Shabbir Ahmed
Nov 16 '18 at 7:06




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53329850%2fmeta-mixin-is-that-even-a-thing-template-meta-programming%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Xamarin.iOS Cant Deploy on Iphone

Glorious Revolution

Dulmage-Mendelsohn matrix decomposition in Python