From: DeMarcus on
Hi,

As I understand, Policies have been widely accepted, but is it the same
with Mixins? Or does people still believe Mixin is a bad way to avoid
Liskov's IS-A principle?

My latest Mixin looks like this.

template<class T>
class CopyMixin
{
public:
typedef std::shared_ptr<T> SPtr;

SPtr copy() const
{
// Use NVI.
return copy_();
}

protected:
virtual SPtr copy_() const = 0;

};


class SomeClass : public CopyMixin<SomeClass>
{
private:
virtual SPtr copy_() const
{
SPtr c = /* Make a proper deep copy. */
return c;
}
};


What do you think about Mixins in general?

And if you have time, what do you think about above CopyMixin?
(Maybe a better copy mixin is already invented. If you know of any,
please show me.)


Thanks,
Daniel

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Mathias Gaunard on
On Jul 6, 8:15 pm, DeMarcus <use_my_alias_h...(a)hotmail.com> wrote:
> Hi,
>
> As I understand, Policies have been widely accepted, but is it the same
> with Mixins? Or does people still believe Mixin is a bad way to avoid
> Liskov's IS-A principle?
>
> My latest Mixin looks like this.
>
> template<class T>
> class CopyMixin
> {

template<typename T, typename Base = some_empty_class_type>
class CopyMixin : Base
{

is better since it allows you to avoid multiple inheritance.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Andy Venikov on
DeMarcus wrote:
> Hi,
>
> As I understand, Policies have been widely accepted, but is it the same
> with Mixins? Or does people still believe Mixin is a bad way to avoid
> Liskov's IS-A principle?
>
> My latest Mixin looks like this.
>
> template<class T>
> class CopyMixin
> {
> public:
> typedef std::shared_ptr<T> SPtr;
>
> SPtr copy() const
> {
> // Use NVI.
> return copy_();
> }
>
> protected:
> virtual SPtr copy_() const = 0;
>
> };
>
>
> class SomeClass : public CopyMixin<SomeClass>
> {
> private:
> virtual SPtr copy_() const
> {
> SPtr c = /* Make a proper deep copy. */
> return c;
> }
> };
>
>
> What do you think about Mixins in general?
>
> And if you have time, what do you think about above CopyMixin?
> (Maybe a better copy mixin is already invented. If you know of any,
> please show me.)

I'm afraid you're confusing mix-ins with CRTP (curiously recurring
template pattern). Your CopyMixin is not a mix-in class, it's a base
template parametrized on the derived class, a classical CRTP.

Mix-ins are classes that inherit from a template parameter.

I.e.

template <typename Base>
class Mixin : public Base
{
};

My personal opinion is that mix-ins are a great tool for certain
circumstances. I don't think that violate Liskov's principle, rather
they "templatize" the subclass. I.e., every concrete Mixin IS-A a
specific Base.

BTW, a couple of years ago Andrei Alexandrescu wrote a paper with Emery
Berger that described a policy-based memory allocation technique that
heavily relied on mix-ins.

[excess quoting deleted--mod]

Andy.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Alf P. Steinbach /Usenet on
* DeMarcus, on 06.07.2010 21:15:
> As I understand, Policies have been widely accepted, but is it the same
> with Mixins? Or does people still believe Mixin is a bad way to avoid
> Liskov's IS-A principle?

I can't think of any good ways to avoid the LSP (Liskov Substitution
Principle).

Whether it's done by a mixin or in some other way, it's generally bad.

Better to strive to honor the LSP.


> My latest Mixin looks like this.
>
> template<class T>
> class CopyMixin
> {
> public:
> typedef std::shared_ptr<T> SPtr;
>
> SPtr copy() const
> {
> // Use NVI.
> return copy_();
> }
>
> protected:
> virtual SPtr copy_() const = 0;
>
> };
>
>
> class SomeClass : public CopyMixin<SomeClass>
> {
> private:
> virtual SPtr copy_() const
> {
> SPtr c = /* Make a proper deep copy. */
> return c;
> }
> };

Usually your "copy" is called "clone", it's like a de facto convention
in C++.
The C++ FAQ for some reason regards it as a special case of "virtual
construction" (the FAQ is the only place I've seen that term used for
that).
E.g., while clone() is typically implemented in terms of the copy
constructor,
one can imagine a newInstance() implemented in terms of the default
constructor.


> What do you think about Mixins in general?

No strong feelings either way.


> And if you have time, what do you think about above CopyMixin?

I think it's nice as an exercise, i.e. for learning about mixins, but it
doesn't
solve any of the following three problems of cloning in C++:

* Checking that cloning is properly implemented.
With the above it's difficult to assert anything about the clone_()
result, since if an override of clone_() is missing in some class,
then that missing override can not assert that it's missing.

* Providing a covariant result.
With the above the copy() result is always shared_ptr<TopMostBase>.

* Avoiding source code repetition of the clone implementation.
With the above every class must, redundantly, implement copy_().


> (Maybe a better copy mixin is already invented. If you know of any,
> please show me.)

The best I've come up with for cloning is a macro.

I discuss that and two other techniques that solve the three problems
above, at
<url:
http://alfps.wordpress.com/2010/06/12/cppx-3-ways-to-mix-in-a-generic-cloning-implementation/>.

I think you'll agree with me that of the three approaches (macro,
middle-man
base class and sideways inheritance with dominance in virtual
inheritance) the
macro wins in simplicity of usage and grokkability of implementation.
:-) But
perhaps there is some fourth and even fifth way. I wouldn't be surprised
if e.g.
Andrei Alexandrescu managed devise something that beats the macro.


Cheers & hth.,

- Alf


--
blog at <url: http://alfps.wordpress.com>

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Ulrich Eckhardt on
DeMarcus wrote:
> As I understand, Policies have been widely accepted, but is it the same
> with Mixins?

Policies or traits are harder to understand than mixins, IMHO. Other
than that, yes, mixins are a good way to separate a single feature out
into a separate class that can be debugged, reused and understood on its
own.

> Or does people still believe Mixin is a bad way to avoid
> Liskov's IS-A principle?

I wouldn't understand a mixin as a baseclass, as its its own
functionality is usually limited. To me, it's rather a feature that is
attached to a class and which is written as a baseclass in C++. In
Python you might use a decorator for that instead, e.g. there is one in
Python that can construct all comparison operators for a class from just
the less-than comparison.

> template<class T>
> class CopyMixin
> {
> public:
> typedef std::shared_ptr<T> SPtr;
>
> SPtr copy() const
> {
> // Use NVI.
> return copy_();
> }
> protected:
> virtual SPtr copy_() const = 0;
> };
>
> class SomeClass : public CopyMixin<SomeClass>
> {
> private:
> virtual SPtr copy_() const
> {
> SPtr c = /* Make a proper deep copy. */
> return c;
> }
> };
[...]
> And if you have time, what do you think about above CopyMixin?

class base
{
// Note: never returns null
virtual base* do_clone() const = 0; // throw(std::exception)
public:
std::auto_ptr<base> clone() const // throw(std::exception)
{
base* p = do_clone();
// must not be null
assert(p);
// must have the same dynamic type
assert(typeid(*p) == typeid(*this));
return std::auto_ptr<base>(p);
}
};

class derived: public base
{
virtual derived* do_clone() const
{ return new derived(*this); }
public:
std::auto_ptr<base> clone() const // throw(std::exception)
{
base* p = do_clone();
// must not be null
assert(p);
// must have the same dynamic type
assert(typeid(*p) == typeid(*this));
return std::auto_ptr<base>(p);
}
}

Notes:
- I did not factor this out into a mixin but just showed the "normal"
implementation for easier reading.
- I now see who I'm sharing the object with: nobody. I have exclusive
ownership due to auto_ptr.
- Check derived class' implementation, both the pointer value and what
it points to as far as possible.
- Use covariant return types so that you can get the right type if you
know that you have a "derived" instance.

If you are happy without the covariant return types, you can just go and
transform "base" into a mixin and implement do_clone() manually for all
derived classes.

Otherwise, you might need two mixins, one being the equivalent to "base"
and the other to "derived". However, then you get a few complications
because one base's pure virtual functions can't be implemented by
inheriting another, you have to get the second baseclass in between your
real base class instead. Something like this:

template<typename T>
class abstract_clonable {...};
template<typename T, typename B>
class clonable: public B {...};
class base: public abstract_clonable<base> {...};
class derived: public clonable<derived, base> {...};


In other words, you have the following order in which classes inherit
from each other:

abstract_clonable<base> - declare clonable interface for base
base - user-defined content
clonable<derived, base> - implement clonable for derived
derived - user-defined content


Uli

--
Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]