Proposal: Mixins for C++

1,282 views
Skip to first unread message

Sebastian Redl

unread,
Aug 27, 2013, 5:14:41 PM8/27/13
to std-pr...@isocpp.org
The ability to inject additional code into a class is something that I have repeatedly missed. Aside from a number of minor uses, I've twice found myself writing a library that would really have benefited from such a feature.

Since someone mentioned this feature a few days back, I thought I'd write up my thoughts on the matter and post them here to gauge interest and gather comments. Preliminary proposal below.


=== Mixins (Class Extension Blocks) for C++ ===

--- Purpose ---
Create a solution for injecting repetitive code into classes that has intuitive
syntax, doesn't use the preprocessor, and lacks the drawbacks of the CRTP.

--- Background ---
There's often a need for classes to contain somewhat repetitive code. For the
purpose of this document, we'll go with three motivating examples, in
increasing complexity.

Example 1: Non-Copyable
Although obsoleted by deleted functions, in C++03 this pattern was used to make
a class non-copyable:

class foo {
private:
  foo(const foo&); // never implemented
  foo& operator =(const foo&); // never implemented
};

This repetitive code was hidden in two ways: with macros or with a
special-purpose base class like boost::noncopyable:

class foo {
  NONCOPYABLE(foo);
};

class foo : boost::noncopyable {
};

The macro expands to the declaration of the two special members above, and in
some cases includes the access specifier. It has the following disadvantages:
- Uses the preprocessor.
- Repeats the class name.
- Changes the access specifier. OR Must be placed in private section.

The base class contains private copy functions itself, which prevents the
compiler from generating definitions of these for the derived class. It has
the following disadvantages:
- Introduces a (usually private) base class. When there is a natural base class
  already, this means it introduces multiple inheritance, which is forbidden in
  some code bases and can even change code generation (e.g. function pointers in
  the Microsoft ABI).
- It could be argued that this is a misuse of base classes.

Example 2: Repetitive Operators (Boost.Operators, Boost.Iterator)
If I want to define my own smart pointer, here's what I have to do:
template <typename T>
class my_ptr {
  // Custom storage logic.
  T* raw;
public:
  // Custom construction and destruction logic.

  T* get() const {
    // Custom access logic.
    return raw;
  }

  // All these can be defined in terms of get():
  T& operator *() const { return *get(); }
  T* operator ->() const { return get(); }
  // This was worse in C++03, when the safe-bool idiom had to be used.
  explicit operator bool() const { return get() != nullptr; }
  bool operator !() const { return get() == nullptr; }
};

Again, one could define a macro to encapsulate these operations, or a base
class. However, the base class solution has the problem that it needs to access
the get() function in the derived class. There are two possible ways to deal
with this.

The first way is to make get() a virtual function in the base class:
template <typename T>
class smart_ptr_base {
public:
  virtual T* get() const = 0;

  // Operators as above.
};
template <typename T>
class my_ptr final : public smart_ptr_base<T> {
  T* get() const override { return raw; }
};

The drawbacks of this solution are:
- Introduces a public (or the operators are inaccessible) base class that could
  be misused as an interface feature.
- Adds a vtable to the class - a 100% size overhead for most smart pointers.
- Adds a virtual call to every operation - a massive performance overhead
  compared to the tiny (probably inlined) functions we have otherwise. Make the
  smart pointer class final, and the compiler might be smart enough to inline
  the operators and de-virtualize the get() call.

The second way is to use the Curiously Recurring Template Pattern:
template <typename Derived, typename T>
class smart_ptr_base {
  const Derived& self() const { return *static_case<const Derived*>(this); }
public:
  T& operator *() const { return *self().get(); }
  // etc.
};
template <typename T>
class my_ptr : public smart_ptr_base<my_ptr<T>, T> {
  T* get() const { return raw; }
};

The drawbacks of this solution are:
- The CRTP introduces its own boilerplate (the self() function).
- The CRTP's workings are unintuitive to those introduced to it - there's a
  reason it's called "curiously" recurring. In particular, the fact that
  Derived is an incomplete type in the body of the CRTP class is a common
  stumbling block, and the reason T must be passed along in the above example
  instead of determined by examining Derived (e.g. to look at a nested typedef).
  Function type deduction in C++14 can help in some cases, but not all.
- The class name must be repeated, including all its template arguments - the
  injected-class-name is not yet visible in the base specification.
- The interface that the CRTP base uses from the derived class must either be
  public, or there must be some friendship between the classes. Specifying the
  entire base class in a friend declaration can be annoying, and friending a
  type alias wasn't possible before C++11, which led to workarounds such as
  iterator_core_access (from Boost.Iterator).

Example 3: Polymorphic Cloning
When you want to make a copy of an object that you only know by a reference or
pointer to the base class, the copy constructor is not sufficient, because it
is not polymorphic. In such cases, the class hierarchy usually provides a clone
function. However, implementing this function in every class is another case of
boilerplate that we want to get rid of.

class base {
public:
  virtual base* clone() const = 0;
};

class foo : public base {
public:
  virtual foo* clone() const { return new foo(*this); }
};

Again, a macro is a popular solution, but requires the class name to be
repeated. A base class with a virtual function is not a solution in this case,
since it does not actually reduce the amount of boilerplate.

A CRTP base class can be used; however, not in the usual fashion:
template <typename Derived>
class cloneable {
  // self()
public:
  Derived* clone() const { return new Derived(self()); }
};
class foo : public base, cloneable<foo> {};

This does not work, because the clone() in cloneable does not override the
clone() in base. To make it work, a wrapper would have to be addded to foo that
is no shorter than directly implementing the function.

Instead, the CRTP class must be injected between base and foo, by templating it
on the base class:
template <typename Base, typename Derived>
class cloneable : public Base {
  // self()
public:
  using Base::Base;
  Derived* clone() const { return new Derived(self()); }
};
class foo : public cloneable<base, foo> {};

The drawbacks of this solution are:
- It obfuscates the inheritance hierarchy.
- Applying multiple such bases gets confusing fast, as they have to be nested.
- Before inherited constructors, correctly forwarding constructors was not
  practical.

--- Proposed Solution ---
Introduce a new code construct, the "mixin". A mixin is similar to a class, but
is not a type by itself. Instead, a mixin is embedded in (mixed into) a class;
its members become members of the class. A mixin is implicitly templated on the
type that embeds it, but can in addition have further template parameters. A
mixin is embedded in a class with a "using mixin" directive.

Example 1: Non-Copyable
Here's a non-copyable mixin:

mixin noncopyable {
  noncopyable(const noncopyable&) = delete;
  noncopyable& operator =(const noncopyable&) = delete;
}
class foo {
  using mixin noncopyable;
};

Here, the compiler will fail to generate the copy functions for foo, because
they would have to call the mixin's copy functions, which are deleted. The mixin
acts like a data member here, including the order of construction (i.e. when
data members and mixins are mixed, the constructors are called in the order of
declaration).

Example 2: Repetitive Operators
Here's the smart_ptr mixin:

mixin smart_ptr {
public:
  // Could use decltype(auto) in C++14, but in some cases we can't, e.g. when
  // we want to use SFINAE tricks on some overloads.
  auto operator *() const -> decltype(*this->get()) { return *this->get(); }
  auto operator ->() const -> decltype(this->get()) { return this->get(); }
  explicit operator bool() const { return this->get() != nullptr; }
  bool operator !() const { return this->get() == nullptr; }
}
template <typename T>
class my_ptr {
public:
  T* get() const { return raw; }
  using mixin smart_ptr;
};

To make this work, we need rules about the access to the embedding class from
the mixin.
Since the mixin is a template, the type of its 'this' pointer is dependent.
The syntax for acessing members is the same as that for access to members of
dependent base classes: use 'this->' to make the expression dependent and delay
lookup until instantiation time.
When the mixin is instantiated, the completeness of the embedding class is
treated exactly as if the mixin's code was directly embedded into the class,
i.e. members prior to the mixin directive are visible, those after are not, and
all the usual rules for ambiguity and changing meanings apply.
Mixins can contain access declarations. Their members have the more restricted
access of the one they have in the mixin and the one the mixin directive is
under. (POD: Just ignore the latter?)
Mixins can access all members of the embedding class, even private ones.

Example 3: Polymorphic Cloning
Here's the cloneable mixin:

mixin cloneable {
public:
  decltype(mixin)* clone() const override { return new decltype(mixin)(*this); }
}
class foo : public base {
public:
  using mixin cloneable;
};

Functions in the mixin override functions the embedding class inherited.
The 'decltype(mixin)' construct names the embedding class. This is to save on
new keywords.

More rules:
Mixins can have additional template parameters, by declaring them using the
usual template syntax, e.g. the smart_ptr mixin could be done like this too:

template <typename T>
mixin smart_ptr {
  T& operator *() const { return *this->get(); }
  // etc.
}
template <typename T>
class my_ptr {
  // as usual
  using mixin smart_ptr<T>;
};

Mixin templates can also be specialized on the additional arguments. It is not
possible to specialize on the embedding type.

Members of the mixin become visible in the embedding class at the point of the
mixin directive. If the mixin is a dependent template instantiation, as in the
example above, non-dependent lookup cannot find them.

Mixins can contain every kind of declaration that classes can, including inner
types, data members, and more mixin directives. Mixins cannot have base classes.
(POD: Should they be able to? The bases could be appended to the list of bases
of the embedding class. What kind of problems could that cause?)

--- Additional Use Cases ---

Building Classes from Blocks:
Imagine you're writing a project_iterator: a wrapper around any iterator that
calls a projection function when being dereferenced.

Here's what this class could look like (some parts omitted):

template <typename Inner, typename Projection>
class project_iterator {
  Inner inner;
  Projection projection;
  using inner_traits = std::iterator_traits<Inner>;
public:
  using reference = decltype(std::declval<Projection>()(
                        *std::declval<Inner>()));
  using value_type = typename std::decay<reference>::type;
  using iterator_category = typename std::conditional<
      std::is_lvalue_reference<reference>::value,
      typename inner_traits::iterator_category,
      std::input_iterator_tag
    >::type;
  // etc.

  // input/output/forward iterator
  reference operator *() const { return projection(*inner); }
  project_iterator& operator ++() { ++inner; return *this; }
  project_iterator operator ++(int) { auto t = *this; ++*this; return t; }

  // bidirectional iterator
  project_iterator& operator --() { --inner; return *this; }
  project_iterator operator --(int) { auto t = *this; --*this; return t; }

  // random-access iterator
  project_iterator& operator +=(difference_type d) { inner += d; return *this; }
  project_iterator& operator -=(difference_type d) { inner -= d; return *this; }
  difference_type operator -(const project_iterator& o) const {
    return inner - o.inner;
  }
  reference operator [](difference_type n) const{ return projection(inner[n]); }
};

On first sight, this looks good. But it comes with a few problems:

- Even when instantiated with a forward iterator, the operations of stronger
  iterators are there. SFINAE cannot be used to detect their absence. When the
  user accidentally uses them, he gets template instantiation errors instead of
  simple lookup failures.
  SFINAE cannot be used to hide the members, because SFINAE only works with
  template functions.
- For an output iterator, difference_type may be void. In such a case, the
  signatures taking difference_type as an argument would be invalid and the
  instantiation of the class would unexpectedly fail. (Note: this is not really
  relevant in this particular example, because a pure output iterator probably
  doesn't allow a function to be applied to its dereference result. However, in
  similar situations, this could be a serious problem.)
  Nasty typedef tricks can be used to work around the instantiation failures,
  e.g. test the inner difference_type for void and use some random type as a
  fallback. However, complexity rises quickly as such tricks are attempted, both
  for the implementer and the user of the iterator.

This situation is most easily demonstrated with iterators, but it appears in
every scenario where a wrapper around an object that could model any concept
from a hierarchy is defined. It can apply to a range library or an I/O library.

To get completely rid of the methods that don't apply requires a tag dispatch to
building blcoks for the final class. Currently, this has to be done with base
classes and looks something like this:

namespace detail {
  template <typename Inner, typename Projection, typename Tag>
  class project_iterator_impl;

  // Base case, supported by everything.
  template <typename Inner, typename Projection>
  class project_iterator_impl<Inner, Projection, input_iterator_tag> {
    using inner_traits = std::iterator_traits<Inner>;
  protected: // so the other parts can access this too
    Inner inner;
    Projection projection;
    // ctors here

  public:
    using reference = decltype(std::declval<Projection>()(
                          *std::declval<Inner>()));
    using value_type = typename std::decay<reference>::type;

    reference operator *() const { return projection(*inner); }
    project_iterator& operator ++() { ++inner; return *this; }
    project_iterator operator ++(int) { auto t = *this; ++*this; return t; }
  };

  template <typename Inner, typename Projection>
  class project_iterator_impl<Inner, Projection, forward_iterator_tag>
      : public project_iterator_impl<Inner, Projection, input_iterator_tag> {
  protected:
    // pull up constructors
    using project_iterator_impl<Inner, Projection, input_iterator_tag>
        ::project_iterator_impl;
  };

  template <typename Inner, typename Projection>
  class project_iterator_impl<Inner, Projection, bidirectional_iterator_tag>
      : public project_iterator_impl<Inner, Projection, forward_iterator_tag> {
  protected:
    // pull up constructors
    using project_iterator_impl<Inner, Projection, forward_iterator_tag>
        ::project_iterator_impl;

  public:
    project_iterator& operator --() { --this->inner; return *this; }
    project_iterator operator --(int) { auto t = *this; --*this; return t; }
  };

  // etc for random_access_iterator
}
template <typename Inner, typename Projection>
class project_iterator : public project_iterator_impl<Inner, Projection,
    typename std::conditional<
        std::is_lvalue_reference<
            decltype(std::declval<Projection>()(
                *std::declval<Inner>()))
          >::value,
        typename inner_traits::iterator_category,
        std::input_iterator_tag
      >::type
    > {
public:
  using iterator_category = typename std::conditional<
      std::is_lvalue_reference<decltype(std::declval<Projection>()(
                                   *std::declval<Inner>()))>::value,
      typename inner_traits::iterator_category,
      std::input_iterator_tag
    >::type;
private:
  using base = project_iterator_impl<Inner, Projection, iterator_category>;
public:
  using base::base;
};

With mixins, the building block game could be massively simplified.

namespace detail {
  template <bool> mixin project_iterator_bidirectional {}
  template <>
  mixin project_iterator_bidirectional<true> {
  public:
    decltype(mixin)& operator --() { --this->inner; return *this; }
    decltype(mixin) operator --(int) { auto t = *this; --*this; return t; }
  }

  template <bool> mixin project_iterator_random_access {}
  template <>
  mixin project_iterator_random_access<true> {
    using self = decltype(mixin);

  public:
    using difference_type = typename self::difference_type;
    using reference = typename self::reference;

    self& operator +=(difference_type d) { this->inner += d; return *this; }
    self& operator -=(difference_type d) { this->inner -= d; return *this; }
    difference_type operator -(const self& o) const {
      return this->inner - o.inner;
    }
    reference operator [](difference_type n) const {
      return this->projection(this->inner[n]);
    }
  }
}

template <typename Inner, typename Projection>
class project_iterator {
  // base case implemented here - doing it this way in the base class model
  // is possible using CRTP, but only as long as the constructors of the pieces
  // don't need the final version already initialized

  using inner_traits = std::iterator_traits<Inner>;
  Inner inner;
  Projection projection;

public:
  // ctors here

  using reference = decltype(std::declval<Projection>()(
                        *std::declval<Inner>()));
  using value_type = typename std::decay<reference>::type;
  using iterator_category = typename std::conditional<
      std::is_lvalue_reference<reference>::value,
      typename inner_traits::iterator_category,
      std::input_iterator_tag
    >::type;

  reference operator *() const { return projection(*inner); }
  project_iterator& operator ++() { ++inner; return *this; }
  project_iterator operator ++(int) { auto t = *this; ++*this; return t; }

  using mixin detail::project_iterator_bidirectional<
      std::is_base_of<std::bidirectional_iterator_tag, iterator_category>::value
      >;
  using mixin detail::project_iterator_random_access<
      std::is_base_of<std::random_access_iterator_tag, iterator_category>::value
      >;
};

On a side note, name conflicts can arise between the embedding class and mixins,
especially for nested types defined for utility, e.g. difference_type and
reference in the example above are defined in both the embedding class, and
the random access mixin. I believe that the best resolution rules are:
- Conflicting variables are an error, with the exception of static constants
  with known values, which get merged if the values are the same.
- Functions overload. If they cannot overload, it's an error.
- Types are merged if they are the same type.

In addition, it might be useful to make it possible for mixins to have sections
that are not made visible to the embedding class (e.g. a "mixin:" access
specifier), although I am hesitant to really do this, because I can see a
pattern developing where the entire class body is always put in a mixin, and a
mixin: specifier is used to create "truly hidden" private sections.

We can add extra syntax for such building blocks along the lines of
ConceptsLite:

namespace detail {
  // no template
  mixin project_iterator_bidirectional {
    // as before
  }
}

template <typename Inner, typename Projection>
class project_iterator {
public:
   ...
   using mixin detail::project_iterator_bidirectional
       requires(std::is_base_of<...>::value);
};

Subsume Partial Classes:
Microsoft added partial classes to C++/CX, where a class can have multiple
bodies that get merged together. Their primary use case for this is the ability
to generate code from XAML files and have it be part of the user class without
having to intrude on that class. And if Herb Sutter has his way, they will find
their way into C++ eventually ("FWIW, think partial classes should be considered
for C++1y as a standard language feature"[1]).
If one is willing to allow a single mixin directive in the user class, mixins
can neatly take over this use case. They support additional construction code,
could possibly support adding base classes, and should be easy to understand for
tools like IntelliSense. (These are the three arguments Herb brought up for
partial classes over a simple #include within the class body in the discussion
linked above.)

[1] http://channel9.msdn.com/Shows/C9-GoingNative/GoingNative-3-The-CCX-Episode-with-Marian-Luparu#c634565677496092669

Klaim - Joël Lamotte

unread,
Aug 27, 2013, 6:50:14 PM8/27/13
to std-pr...@isocpp.org
Very interesting feature.
I have a lot of recent code that would benefit a lot in clarity by using such kind of feature
because composing a class public interface happen often and there is, as demonstrated here, no easy way to do it in C++.

Questions:

1. does mixin member function have to be defined before the "using" call? does all the mixin code have to be in the declaration?
    can it be mixins be written with declaration and definition separate? (the same question but said differently)

2.


Example 3: Polymorphic Cloning
Here's the cloneable mixin:
mixin cloneable {
public:
  decltype(mixin)* clone() const override { return new decltype(mixin)(*this); }
}
class foo : public base {
public:
  using mixin cloneable;
};
Functions in the mixin override functions the embedding class inherited.
The 'decltype(mixin)' construct names the embedding class. This is to save on
new keywords.


I don't understand why  the return type of clone() is decltype(mixin)*.
If this clone() function is overloading base::clone(), then shouldn't it return base*?
If yes, then this clonable mixin should be templated with the base class as parameter.
Am I correct?

3. 


In addition, it might be useful to make it possible for mixins to have sections
that are not made visible to the embedding class (e.g. a "mixin:" access
specifier), although I am hesitant to really do this, because I can see a
pattern developing where the entire class body is always put in a mixin, and a
mixin: specifier is used to create "truly hidden" private sections.

I have no strong opinion but here is my thinking on this:
It appear that mixins would be good to compose the public interface of a class at least.
Now, if it's always "public" and access depends on access of the using declaration,
it means that if someone wants to compose a class with private and public parts,
in which case he can:
 1. make sure there is are mixins that have a correct interface for public access and another mixins that are used in private access
     This forces mixin implementor to sometime cut their work into several mixins, which look a bit like it would make the code less easy to follow
     (like when there is too much callback calls);
 2. use mixins only for public parts as expected, use private inheritance or member object composition for non-public parts;

Now if mixins have accessors inside, there seem to be several ways possibilities:
 A. the mixin accessor is always used, whatever the using call context:

mixin K { 
     private:
     void foo();
}

class U
{
public:
    using mixin K; // foo() is private and accessible by U members
};

B. mixin accessors are only public and private: private code is not exposed to the mixin user at all


mixin K { 
     private:
     void foo();
     public:
     void bar();
}

class U
{
public:
    using mixin K; // foo() is not accessible by U members, bar() is public
};

class V
{
private:
    using mixin K; // bar() is accessible only by V members, foo() is still not accessible at all
};


C. mixin accessors will have the lower access right allowed between the mixin code and the using code:

mixin K { 
     private:
     void foo();
     protected:
     void meow();
     public:
     void bar();
}

class U
{
public:
    using mixin K;
    /* foo() is public
       meow() is protected (accessible by U members and U child classes)
       bar() is private (accessible by U members only)
    */
};

class V
{
private:
    using mixin K; 
    /* foo() is private (accessible by V members only)
       meow() is private
       bar() is private
    */
};

class W
{
protected:
    using mixin K; 
    /* foo() is protected (accessible by U members and U child classes)
       meow() is protected
       bar() is private
    */
};

D. mixin accessors follow exactly the same accessor logic than class inheritance (which is like C but bar() is never accesible):


mixin K { 
     private:
     void foo();
     protected:
     void meow();
     public:
     void bar();
}

class U
{
public:
    using mixin K;
    /* foo() is public
       meow() is protected (accessible by U members and U child classes)
       bar() is never accessible
    */
};

class V
{
private:
    using mixin K; 
    /* foo() is private (accessible by V members only)
       meow() is protected
       bar() is never accessible
    */
};

class W
{
protected:
    using mixin K; 
    /* foo() is protected (accessible by U members and U child classes)
       meow() is protected
       bar() is never accessible
    */
};

I guess this needs some thinking.


Joel Lamotte

Klaim - Joël Lamotte

unread,
Aug 27, 2013, 6:52:28 PM8/27/13
to std-pr...@isocpp.org
One last thing:
without accessors, I believe mixin implementations would be a bit difficult
if it needs to add member objects and need to keep them private.


Sebastian Redl

unread,
Aug 27, 2013, 7:43:45 PM8/27/13
to std-pr...@isocpp.org


On Wednesday, August 28, 2013 12:50:14 AM UTC+2, Klaim - Joël Lamotte wrote:
Very interesting feature.

Thank you.


Questions:

1. does mixin member function have to be defined before the "using" call? does all the mixin code have to be in the declaration?
    can it be mixins be written with declaration and definition separate? (the same question but said differently)

Mixin member implementations can be out of line, and even after a class has embedded the mixin, but keep in mind that a mixin is always like a template, The implementations need to be visible to whoever tries to instantiate them (by using them).
 

2.

Example 3: Polymorphic Cloning
Here's the cloneable mixin:
mixin cloneable {
public:
  decltype(mixin)* clone() const override { return new decltype(mixin)(*this); }
}
class foo : public base {
public:
  using mixin cloneable;
};
Functions in the mixin override functions the embedding class inherited.
The 'decltype(mixin)' construct names the embedding class. This is to save on
new keywords.


I don't understand why  the return type of clone() is decltype(mixin)*.
If this clone() function is overloading base::clone(), then shouldn't it return base*?
If yes, then this clonable mixin should be templated with the base class as parameter.
Am I correct?


clone() typically has a covariant return type, so that when I call clone() on an object statically known to be at least a Derived, I get a Derived* back instead of a Base*. That's why the mixin's clone() returns decltype(mixin)*.

 
3. 


Now if mixins have accessors inside, there seem to be several ways possibilities:

You have pretty much enumerated the access possibilities given the current access specifiers. But my worry goes beyond just access and concerns visibility:

template <typename T>
mixin Foo {
  using my_secret_helper_type = complicated_metaprogram<T>;
  // how do I keep my_secret_helper_type from colliding with types in embedding classes?
  // I can't open a namespace here, but I don't want to start with prefixes again

mixin:
  using this_can_never_conflict = other_metaprogram<T>;
  // awesome, I can use these without worries, because they're truly local to this class
}

I see these options to solve this problem:
1) Do nothing. Have the users use prefixes. This seems extremely inelegant to me.
1a) Merge what can be merged, but otherwise error out, as I described in my original post. Marginally better than 1).
2) Have declarations in the embedding class shadow those in mixins. Except for overloads maybe? But what if two mixins conflict? Earlier shadows later? Later shadows earlier? Declarations co-exist but are ambiguous when accessed?
2a) Embedding class shadows mixins, functions don't overload, multiple mixins coexist and are ambiguous in access. This is the "let's pretend we're still mixing in CRTP base classes" model. But given that I want the model to be "these are put into the class", that's very unintuitive.
3) Provide mixin: or an equivalent way of allowing mixins to hide their implementation details, and have other conflicting parts generate an error. Sounds reasonable, except that, as I said, this would mean that mixins provide a feature that C++ doesn't otherwise have, and I'm worried that they'll be used for that feature alone, leading to obfuscated code. But maybe I shouldn't be worried about that. I can still worry about implementability, though.
3a) Combine 3) with the merging from 1a) for non-hidden things. I like this merging - it feels intuitive and right. But maybe that's just because of where I'm coming from.

Róbert Dávid

unread,
Aug 27, 2013, 7:59:34 PM8/27/13
to std-pr...@isocpp.org
 
All your example cases can be solved with a good (private or public) base class, I try to show you how:

Example 1: Non-Copyable
It would be better if you start from C++11 (or even the current draft; N3690 at this time)
class foo {
  foo
(const foo&) = delete;
  foo
& operator=(const foo&) = delete;
};
(Side note: let me point out that noncopyable and noncopyassignable are two different things, although very frequently used together.)
The only thing is missing (?) is a standard std::noncopyable "mixin": the one above, with a correct name. This solution does not use macros, does not repeat the class name, and does not change the access classifier anywhere.
Base classes add a 'feature' to a class, some people say it is "is-a" relation. Saying that Foo is-a noncopyable thing isn't worse than Java or C# saying everything is-a Object, so I don't believe it is a misuse of base classes. I don't really see how an empty base class can screw up code generation, maybe with a bad compiler, but in that case you are probably not even using C++11, or if the multiple inheritance is banned because of policy reasons, then you are asking a language extension because you don't use the whole language..


Example 2: Repetitive Operators (Boost.Operators, Boost.Iterator)

You can do CRTP a lot better:
template <typename Derived>
class smart_ptr_base {
 
const Derived& self() const { return *static_cast<const Derived*>(this); }
  typedef decltype(self.get()) T;
public
:

  T
& operator *() const { return *self().get(); }
 
// etc.
};
template <typename T>
class my_ptr : public smart_ptr_base<my_ptr> {

  T
* get() const { return raw; }
};
Works in VS2012 already.. Note: there is no need to write my_ptr<T>, same reason why you don't write the template parameter out while defining the constructors.


- The CRTP's workings are unintuitive to those introduced to it - there's a reason it's called "curiously" recurring. In particular, the fact that Derived is an incomplete type in the body of the CRTP class is a common stumbling block, and the reason T must be passed along in the above example instead of determined by examining Derived (e.g. to look at a nested typedef). Function type deduction in C++14 can help in some cases, but not all.
- The class name must be repeated, including all its template arguments - the injected-class-name is not yet visible in the base specification.
None of this is true, see above example.


- The interface that the CRTP base uses from the derived class must either be public, or there must be some friendship between the classes. Specifying the entire base class in a friend declaration can be annoying, and friending a type alias wasn't possible before C++11, which led to workarounds such as iterator_core_access (from Boost.Iterator).
Well, ok, you are right, but are you trying to give private functionality through a mixin? I fail to see where can that be useful.

Example 3: Polymorphic Cloning
If you have polymorphic cloning, you have to have or your clone function virtual, otherwise you will call the base class' clone from the base pointer/reference. You mention macros as downside again, but even your virtual function example doesn't have any...

So sorry but -1. Mixins are dumbed-down versions of multiple inheritance so languages without that can have that functionality, but quite handicapped in a few cases. C++/CX is such a language, so it needs mixins, aka partial classes. There is absolutely no need for mixins in proper C++, as long as you use the language properly. It does need a few tweaks here and there, but I don't feel mixins are such.

If something is missing, the standard "mixin" classes, starting with std::non_copyable, std::non_movable, and so on. Call for papers is until Friday, figure out what these are, and I help writing the proposal :)

Regards, Robert

(For crying out loud Google, let me send the mail already!)

Sean Middleditch

unread,
Aug 27, 2013, 8:13:44 PM8/27/13
to std-pr...@isocpp.org
Nice.  I've been idly mulling the same topic for over a year now but hadn't really explored it as thoroughly as you have.

I would definitely include accessors.  The standard three to me make perfect sense.  private implies only access to the mixin methods, protected is to the mixin or its mixed-into class/descendants, and public means, well, public.  Might even allow the using syntax to imply an additional restricted accessibility as per class inheritance, or even just reuse that syntax.  e.g.

   // silly example mixin that might as well just be a regular base class
   class m mixin {
   public:
      void f() { return 3; } 
   };

   class c final : private m {
   };

   c v;
   v.f(); // error: private

I would also clarify that a mixin is not a type.  You can't have a pointer to a mixin or such.  It's essentially a block of syntactic sugar for a template-like mechanism (though unlike a templated type, it's still not a type).  Spelling all the ramifications of this would be an undertaking, but it's IMO essential to what the core idea of a mixin is or how it could even be implemented reasonably.

You might consider how these could play with constraints, which is a feature that the CRTP method grants today (or once concepts lite are supported, anyway) but mixins do not.

    mixin foo
      requires(Comparable<*this>, is_base_of<base_type, *this>)
    { ... };

If this is supported, then can you overload mixins like you can templates?  Or simply do static assertions on requirements?  This also removes the need for any kind of new "static abstract method" syntax that other languages' mixin sytems have typically provided (e.g. the requirement that get() be provided by any class using the mixin).

Sean Middleditch

unread,
Aug 27, 2013, 8:54:43 PM8/27/13
to std-pr...@isocpp.org
On Tuesday, August 27, 2013 4:59:34 PM UTC-7, Róbert Dávid wrote:
You can do CRTP a lot better:
template <typename Derived>
class smart_ptr_base {
 
const Derived& self() const { return *static_cast<const Derived*>(this); }
  typedef decltype(self.get()) T;
public
:
  T
& operator *() const { return *self().get(); }
 
// etc.
};
template <typename T>
class my_ptr : public smart_ptr_base<my_ptr> {
  T
* get() const { return raw; }
};
Works in VS2012 already.. Note: there is no need to write my_ptr<T>, same reason why you don't write the template parameter out while defining the constructors.

That is an incredibly simplistic example of the CRTP mixin pattern.  Try a class that wants to use two mixins which each partially implement some of the polymorphic interface of a base.  It gets unwieldly, quickly.
 
Example 3: Polymorphic Cloning
If you have polymorphic cloning, you have to have or your clone function virtual, otherwise you will call the base class' clone from the base pointer/reference. You mention macros as downside again, but even your virtual function example doesn't have any...

So sorry but -1. Mixins are dumbed-down versions of multiple inheritance so languages without that can have that functionality, but quite handicapped in a few cases. C++/CX is such a language, so it needs mixins, aka partial classes. There is absolutely no need for mixins in proper C++, as long as you use the language properly. It does need a few tweaks here and there, but I don't feel mixins are such.

They aren't just that.  C++'s multiple inheritance also does not solve certain problems.  Mixins without MI aren't a complete solution.  MI isn't a complete solution.  Heck, mixins with MI probably won't be a complete solution, but it will be more complete at least.

And then there's the weird recursive situations, which granted are very exceptional in a good design, but I've seen come up several time.  Example:

   struct base {
     virtual base& foo() = 0;
     virtual base& bar() = 0;
   };

   template <class Derived, class Base>
   struct mixin_foo : public Base {
     int value;
     Derived& foo() override;
   };

   template <class Derived, class Base>
   struct mixin_bar : public Base {
     void something(int);
     Derived& bar() override {
       something(static_cast<Derived&>(*this).value);
       return *this;
     }
   };

   struct derived : publix mixin_foo<derived, mixin_bar<mixin_foo<derived, ???>, base>>
   {
      int value = 5; // note that mixin_bar wants to use mixin_foo's value, not derived's value
   };

Oppose this to a mixin solution:

   struct base {
     virtual base& foo() = 0;
     virtual base& foo() = 0;
   };

There's no way to realistically fill in the ??? part as mixin_bar's Derived type is itself dependent on mixin_bar. Again, it's a weird case, and every time I've seen it myself I've found other (arguably much better) ways to do what I wanted, but it is a general pattern that C++ multiple inheritance and CRTP are not an alternative to mixins.  You can't _compose mixins_ with CRTP.
     

Nevin Liber

unread,
Aug 27, 2013, 8:58:27 PM8/27/13
to std-pr...@isocpp.org
On 27 August 2013 16:14, Sebastian Redl <wasti...@gmx.net> wrote:
=== Mixins (Class Extension Blocks) for C++ ===

0.  I would get rid of the references to how things were written back in the C++03 days.  This is for C++17; it should be solving the things we can't (easily) write with C++14 and Concepts Lite.

1.  Change the syntax by making the implicit template argument explicit, as in:

template<typename T>
mixin noncopyable
{ /*... */ };

This gives you a name for the type instantiated (instead of the weird decltype(mixin)) and makes it obvious it is templated.  While it violates DRY (Don't Repeat Yourself), instantiating it should also require specifying T, as it is more uniform with the rest of the language.
 Example 1: Non-Copyable
Here's a non-copyable mixin:

mixin noncopyable {
  noncopyable(const noncopyable&) = delete;
  noncopyable& operator =(const noncopyable&) = delete;
}
class foo {
  using mixin noncopyable;
};

Here, the compiler will fail to generate the copy functions for foo, because
they would have to call the mixin's copy functions, which are deleted.

For each of the following can you tell me if they are intended to be (a) copyable, (b) non-copyable or (c) non-compileable?

struct One {
    using mixin noncopyable;
};

struct Two {
    using mixin noncopyable;
    Two(Two const&) = default;
    Two& operator=(Two const&) = default;
};

struct Three {
    using mixin noncopyable;
    Three(Three const&) {}
    Three& operator=(Three const&) { return *this; }
};

Anyway, just my initial questions...
--
 Nevin ":-)" Liber  <mailto:ne...@eviloverlord.com(847) 691-1404

Sean Middleditch

unread,
Aug 27, 2013, 8:59:43 PM8/27/13
to std-pr...@isocpp.org
On Tuesday, August 27, 2013 5:54:43 PM UTC-7, Sean Middleditch wrote:

Oppose this to a mixin solution:

   struct base {
     virtual base& foo() = 0;
     virtual base& foo() = 0;
   };

And I got distracted and cut short writing up that mixin example.  

   struct base {
     virtual base& foo() = 0;
     virtual base& bar() = 0;
   };

   struct mixin_foo mixin {
     int value;
     auto decltype(*this) foo();
   };

   struct mixin_bar mixin {
     void something(int);
     auto bar() {
       something(this->value);
       return *this;
     }
   };

   struct derived : public base
   {
      using mixin mixin_foo;
      using mixin mixin_bar { using mixin_foo::value; } // sample syntax
      int value = 5;
   };

I'm not super fond of the syntax there, but the idea is illustrated as well as it can for such a silly example I think.

corn...@google.com

unread,
Aug 28, 2013, 6:44:04 AM8/28/13
to std-pr...@isocpp.org


On Wednesday, August 28, 2013 1:59:34 AM UTC+2, Róbert Dávid wrote:
 
All your example cases can be solved with a good (private or public) base class, I try to show you how:

Example 1: Non-Copyable
It would be better if you start from C++11 (or even the current draft; N3690 at this time)
class foo {
  foo
(const foo&) = delete;
  foo
& operator=(const foo&) = delete;
};
(Side note: let me point out that noncopyable and noncopyassignable are two different things, although very frequently used together.)
The only thing is missing (?) is a standard std::noncopyable "mixin": the one above, with a correct name. This solution does not use macros, does not repeat the class name, and does not change the access classifier anywhere.
Base classes add a 'feature' to a class, some people say it is "is-a" relation. Saying that Foo is-a noncopyable thing isn't worse than Java or C# saying everything is-a Object, so I don't believe it is a misuse of base classes. I don't really see how an empty base class can screw up code generation, maybe with a bad compiler,

The very compiler you're using below has bigger member function pointers for classes that use MI. It may not be a big thing, but it's there.
 
but in that case you are probably not even using C++11, or if the multiple inheritance is banned because of policy reasons, then you are asking a language extension because you don't use the whole language..

Example 2: Repetitive Operators (Boost.Operators, Boost.Iterator)

You can do CRTP a lot better:
template <typename Derived>
class smart_ptr_base {
 
const Derived& self() const { return *static_cast<const Derived*>(this); }
  typedef decltype(self.get()) T;
public
:
  T
& operator *() const { return *self().get(); }
 
// etc.
};
template <typename T>
class my_ptr : public smart_ptr_base<my_ptr> {
  T
* get() const { return raw; }
};
Works in VS2012 already.. Note: there is no need to write my_ptr<T>, same reason why you don't write the template parameter out while defining the constructors.

Nice that it works in VS2012. Have you actually tried instantiating it?
It's still invalid, and won't compile in Clang or GCC. You can't use `this` (even implicitly) at the top level of a class, even inside a decltype. Even if you could, at that point the type Derived is incomplete and the get() call would be invalid. And finally, no, you can't omit the template arguments to my_ptr when passing it to the base class, because as [basic.scope.pdecl]p7 says, "The point of declaration for an injected-class-name (Clause 9) is immediately following the opening brace
of the class definition." The opening brace is of course after the base class specifier, so the injected-class-name doesn't exist there.
Now you could argue that these are defects in the standard, but the fact is that your "simple" CRTP example is currently not valid C++, and thus not a counterargument to my points.
 

- The CRTP's workings are unintuitive to those introduced to it - there's a reason it's called "curiously" recurring. In particular, the fact that Derived is an incomplete type in the body of the CRTP class is a common stumbling block, and the reason T must be passed along in the above example instead of determined by examining Derived (e.g. to look at a nested typedef). Function type deduction in C++14 can help in some cases, but not all.
- The class name must be repeated, including all its template arguments - the injected-class-name is not yet visible in the base specification.
None of this is true, see above example.

Even if above example was valid, that wouldn't change the fact that it's still CRTP. I claim that CRTP by its very nature is not intuitive - saying, "but using CRTP doesn't need the extra boilerplate that you also complained about" doesn't contradict my core argument.
 

- The interface that the CRTP base uses from the derived class must either be public, or there must be some friendship between the classes. Specifying the entire base class in a friend declaration can be annoying, and friending a type alias wasn't possible before C++11, which led to workarounds such as iterator_core_access (from Boost.Iterator).
Well, ok, you are right, but are you trying to give private functionality through a mixin? I fail to see where can that be useful.

I don't understand what you mean by "trying to give private functionality through a mixin". What I want is for mixins to be be able to access functionality in the embedding class that users of the embedding class cannot use.
 

Example 3: Polymorphic Cloning
If you have polymorphic cloning, you have to have or your clone function virtual, otherwise you will call the base class' clone from the base pointer/reference.

And your point is? The base version is virtual, and therefore functions overriding it are also virtual. I'm not sure what you're saying here.
 
You mention macros as downside again, but even your virtual function example doesn't have any...

I mention macros as a possible solution, not as a downside of something. You can define a macro
#define CLONEABLE(clazz) clazz* clone() const { return new clazz(*this; }
and put that in the class body; that's one way to solve the issue, but it uses macros, and replacing macros by fully-integrated solutions is generally a good thing. I didn't bother to spell this solution out, because it should be completely obvious.
 

So sorry but -1. Mixins are dumbed-down versions of multiple inheritance so languages without that can have that functionality, but quite handicapped in a few cases.

I see mixins as a clean solution to a use case that is currently imperfectly solved in C++ with multiple inheritance and CRTP, or macros. I presented the reasons why the current solutions are imperfect. Your counterargument doesn't compile, proving me right on multiple levels (in particular the non-intuitiveness and level of difficulty of the current solution).
 
C++/CX is such a language, so it needs mixins, aka partial classes.

Partial classes are not mixins, since they are not reusable. They are an underspecified hack to make life easier for the developers of visual form designers and other round-tripping code generators.
 
There is absolutely no need for mixins in proper C++, as long as you use the language properly. It does need a few tweaks here and there, but I don't feel mixins are such.

I'm curious to hear what tweaks you think are necessary.
 

If something is missing, the standard "mixin" classes, starting with std::non_copyable, std::non_movable, and so on. Call for papers is until Friday, figure out what these are, and I help writing the proposal :)


I have absolutely no interest in writing a hurried paper to get a few hacky special-purpose workarounds into the language.
 

corn...@google.com

unread,
Aug 28, 2013, 6:49:16 AM8/28/13
to std-pr...@isocpp.org


On Wednesday, August 28, 2013 2:13:44 AM UTC+2, Sean Middleditch wrote:
Nice.  I've been idly mulling the same topic for over a year now but hadn't really explored it as thoroughly as you have.

I would definitely include accessors.  The standard three to me make perfect sense.  private implies only access to the mixin methods, protected is to the mixin or its mixed-into class/descendants, and public means, well, public.

Is there a use-case for things that are accessible to the embedding class but not its descendants?

 
I would also clarify that a mixin is not a type.  You can't have a pointer to a mixin or such.  It's essentially a block of syntactic sugar for a template-like mechanism (though unlike a templated type, it's still not a type).  Spelling all the ramifications of this would be an undertaking, but it's IMO essential to what the core idea of a mixin is or how it could even be implemented reasonably.

Yes, that's an excellent point - I should definitely make that more explicit.
 

You might consider how these could play with constraints, which is a feature that the CRTP method grants today (or once concepts lite are supported, anyway) but mixins do not.

    mixin foo
      requires(Comparable<*this>, is_base_of<base_type, *this>)
    { ... };

If this is supported, then can you overload mixins like you can templates?

I don't think ConceptsLite allows you to overload class templates, does it? But I agree that being able to specify requirements on mixins would be a good thing.

Róbert Dávid

unread,
Aug 28, 2013, 6:54:17 AM8/28/13
to std-pr...@isocpp.org

That is an incredibly simplistic example of the CRTP mixin pattern.  Try a class that wants to use two mixins which each partially implement some of the polymorphic interface of a base.  It gets unwieldly, quickly.

I didn't simplify CRTP as a whole, I just simplified your example to show why I find it as a bad example for this argument.

 They aren't just that.  C++'s multiple inheritance also does not solve certain problems.  Mixins without MI aren't a complete solution.  MI isn't a complete solution.  Heck, mixins with MI probably won't be a complete solution, but it will be more complete at least.

I disagree: Please show me what you can do with mixins but cannot with MI.

And then there's the weird recursive situations, which granted are very exceptional in a good design, but I've seen come up several time.  Example:

   struct base {
     virtual base& foo() = 0;
     virtual base& bar() = 0;
   };

   template <class Derived, class Base>
   struct mixin_foo : public Base {
     int value;
     Derived& foo() override;
   };

   template <class Derived, class Base>
   struct mixin_bar : public Base {
     void something(int);
     Derived& bar() override {
       something(static_cast<Derived&>(*this).value);
       return *this;
     }
   };

   struct derived : publix mixin_foo<derived, mixin_bar<mixin_foo<derived, ???>, base>>
   {
      int value = 5; // note that mixin_bar wants to use mixin_foo's value, not derived's value
   };
 

Oppose this to a mixin solution:

   struct base {
     virtual base& foo() = 0;
     virtual base& foo() = 0;
   };

There's no way to realistically fill in the ??? part as mixin_bar's Derived type is itself dependent on mixin_bar. Again, it's a weird case, and every time I've seen it myself I've found other (arguably much better) ways to do what I wanted, but it is a general pattern that C++ multiple inheritance and CRTP are not an alternative to mixins.  You can't _compose mixins_ with CRTP.

How do you want this to be compiled? When is the function inside mixin_bar parsed, and what will be the type of the .value (because without including it to a class, that name isn't even declared!)

Regards, Robert

corn...@google.com

unread,
Aug 28, 2013, 7:06:19 AM8/28/13
to std-pr...@isocpp.org


On Wednesday, August 28, 2013 2:58:27 AM UTC+2, Nevin ":-)" Liber wrote:
On 27 August 2013 16:14, Sebastian Redl <wasti...@gmx.net> wrote:
=== Mixins (Class Extension Blocks) for C++ ===

0.  I would get rid of the references to how things were written back in the C++03 days.  This is for C++17; it should be solving the things we can't (easily) write with C++14 and Concepts Lite.

That's probably a good idea. I went with noncopyable for the first example because it's simple and so well-known.
 

1.  Change the syntax by making the implicit template argument explicit, as in:

template<typename T>
mixin noncopyable
{ /*... */ };

This gives you a name for the type instantiated (instead of the weird decltype(mixin)) and makes it obvious it is templated.  While it violates DRY (Don't Repeat Yourself), instantiating it should also require specifying T, as it is more uniform with the rest of the language.

I really, really don't want this. I agree that the uniformity is a good argument for it, but I also think that avoiding repeating the class name when pulling in the mixin is a very good thing that makes it look a lot less hacky, less like the macro approach. (Is that a "reductio-ad-macrum" fallacy?)
The decltype(mixin) syntax could be replaced by simply specifying that the name of the mixin names the embedding type inside the mixin. Would that be better? It would be more concise, and in a way less weird, but it could also be very surprising.

As far as making the template obvious goes, we're already moving away from that with the terse template syntax coming up. So this extension wouldn't be a weird exception.
 

For each of the following can you tell me if they are intended to be (a) copyable, (b) non-copyable or (c) non-compileable?

As I said, this is a point that still needs some consideration to find the right solution that is intuitive and useful. But my currently preferred solution would result in the following:
 

struct One {
    using mixin noncopyable;
};

Not copyable. The compiler cannot define the implicit functions for One.
 

struct Two {
    using mixin noncopyable;
    Two(Two const&) = default;
    Two& operator=(Two const&) = default;
};

Whatever happens in the same situation for a noncopyable base - I think it compiles, but the functions will be defined as deleted.
 

struct Three {
    using mixin noncopyable;
    Three(Three const&) {}
    Three& operator=(Three const&) { return *this; }
};

This is copyable, unless the noncopyable trait suppresses the default constructor, in which case it's not compileable.
 

Róbert Dávid

unread,
Aug 28, 2013, 7:17:32 AM8/28/13
to std-pr...@isocpp.org, corn...@google.com

Nice that it works in VS2012. Have you actually tried instantiating it?
It's still invalid, and won't compile in Clang or GCC. You can't use `this` (even implicitly) at the top level of a class, even inside a decltype. Even if you could, at that point the type Derived is incomplete and the get() call would be invalid. And finally, no, you can't omit the template arguments to my_ptr when passing it to the base class, because as [basic.scope.pdecl]p7 says, "The point of declaration for an injected-class-name (Clause 9) is immediately following the opening brace of the class definition." The opening brace is of course after the base class specifier, so the injected-class-name doesn't exist there.
Now you could argue that these are defects in the standard, but the fact is that your "simple" CRTP example is currently not valid C++, and thus not a counterargument to my points.

Yes, of course, it works fine in every way. This was the compiler at hand, and I didn't try in other compilers, didn't think this can be nonstandard (MSVC surprises me every now and then in being nonstandard, but I think this is a convenient extension.)

 
Even if above example was valid, that wouldn't change the fact that it's still CRTP. I claim that CRTP by its very nature is not intuitive - saying, "but using CRTP doesn't need the extra boilerplate that you also complained about" doesn't contradict my core argument.

Instead ditching CRTP for an (in my opinion) infernal, but more intuitive solution, adding more complication to the language without any real benefit, what about trying to make CRTP more intuitive? (For start, we could add the way VS2012 defines the injected-class-name.). Please tell why do you think it is unintuitive, to see if we can help improve it. My point is: instead of adding new, complex tools to the language, improve the current tools that already able to do the same job.

 
  
There is absolutely no need for mixins in proper C++, as long as you use the language properly. It does need a few tweaks here and there, but I don't feel mixins are such.

I'm curious to hear what tweaks you think are necessary.
 
Well, this list is the "C++ standard proposals", if people didn't think it needs tweaks here and there, it would been deserted long ago.

 
If something is missing, the standard "mixin" classes, starting with std::non_copyable, std::non_movable, and so on. Call for papers is until Friday, figure out what these are, and I help writing the proposal :)

I have absolutely no interest in writing a hurried paper to get a few hacky special-purpose workarounds into the language.

The comment about the deadline was trying to be a joke, the standard 'mixin classes' is still something we should have. Having a standard way to disable copy (without the verbose = delete syntax) is not "special purpose".

Regards, Robert

David Krauss

unread,
Aug 28, 2013, 7:21:09 AM8/28/13
to std-pr...@isocpp.org
Really what you're describing is another form of inheritance. Rather than being a superclass or subclass, the mixin is a peer of the target.

The tricky part is deciding the relative order of declaration and initialization of the mixin members. C++11 is more sensitive than C++03 was to the declaration order of class members, because we have decltype() now. You could define the members at the using declaration, but this is a potential source of errors. (Unless you intended this, I'm not sure why you made it a using declaration rather than a base specifier.)

Some new syntax would be required to run the constructor of the mixin. It would be odd to mention a name from a using declaration in a constructor mem-initializer.

Recently I suggested inferring member declarations from a concept applied to a template parameter used as a base class. A name that is required to exist doesn't really need to be considered type-dependent. Applied to an incomplete class, the principle could help bridge the gap that seems to be causing confusion in the above posts. Not to make a blanket judgment about this proposal, but CRTP can probably be improved by such relatively minor changes.

Klaim - Joël Lamotte

unread,
Aug 28, 2013, 7:25:44 AM8/28/13
to std-pr...@isocpp.org
On Wed, Aug 28, 2013 at 1:21 PM, David Krauss <pot...@gmail.com> wrote:
Really what you're describing is another form of inheritance. Rather than being a superclass or subclass, the mixin is a peer of the target.


I don't agree at all. Inheritance is about relationship between types. Here it's about injecting code into a type definition. There is no relationship
between the mixin and it's use.
It's closer to member object composition, but applied to interfaces.
 
The tricky part is deciding the relative order of declaration and initialization of the mixin members.

I expect it to be exactly the same as if you copy-pasted the mixing code into the user class.
 
C++11 is more sensitive than C++03 was to the declaration order of class members, because we have decltype() now. You could define the members at the using declaration, but this is a potential source of errors. (Unless you intended this, I'm not sure why you made it a using declaration rather than a base specifier.)


Can you clarify what is the relationship between decltype and the order of class members?
 
Some new syntax would be required to run the constructor of the mixin. It would be odd to mention a name from a using declaration in a constructor mem-initializer.


Maybe you misread, the proposed mixin is not supposed to have a constructor. It's not a type.
It's a pack of code.

corn...@google.com

unread,
Aug 28, 2013, 7:59:51 AM8/28/13
to std-pr...@isocpp.org, corn...@google.com


On Wednesday, August 28, 2013 1:17:32 PM UTC+2, Róbert Dávid wrote:

Nice that it works in VS2012. Have you actually tried instantiating it?
It's still invalid, and won't compile in Clang or GCC. You can't use `this` (even implicitly) at the top level of a class, even inside a decltype. Even if you could, at that point the type Derived is incomplete and the get() call would be invalid. And finally, no, you can't omit the template arguments to my_ptr when passing it to the base class, because as [basic.scope.pdecl]p7 says, "The point of declaration for an injected-class-name (Clause 9) is immediately following the opening brace of the class definition." The opening brace is of course after the base class specifier, so the injected-class-name doesn't exist there.
Now you could argue that these are defects in the standard, but the fact is that your "simple" CRTP example is currently not valid C++, and thus not a counterargument to my points.

Yes, of course, it works fine in every way. This was the compiler at hand, and I didn't try in other compilers, didn't think this can be nonstandard (MSVC surprises me every now and then in being nonstandard, but I think this is a convenient extension.)

This is really curious, because it doesn't actually compile once you try to instantiate it:

 
Even if above example was valid, that wouldn't change the fact that it's still CRTP. I claim that CRTP by its very nature is not intuitive - saying, "but using CRTP doesn't need the extra boilerplate that you also complained about" doesn't contradict my core argument.

Instead ditching CRTP for an (in my opinion) infernal,

I didn't think it was that bad ... ;-)
 
but more intuitive solution, adding more complication to the language without any real benefit, what about trying to make CRTP more intuitive?

Making the injected-class-name available in the base class list gets rid of completely unnecessary syntax clutter. That's a good thing, but it doesn't really increase the ease of CRTP.

My main objections are:
1) The very nature of the curious recursion in the CRTP makes it unintuitive. Deriving from a class template that you gave the deriving class tied a knot in the brain of every single person I've ever explained it to. That includes people I've explained to how Java's IComparable works. (It's also curiously recurring, even though it's not a template.)
2) A CRTP base isn't actually bound to the deriving class. That is, I can do "class foo : public crtp<bar>", and the compiler can't immediately say, "This is wrong!". And currently (with the injected-class-name not available in the base list), such an error is actually easy to make - just make an error in specifying the template arguments to your own class. Mixins simply make this error impossible. (This, by the way, is a big argument for me against Nevin's suggestion to make the embedding class argument explicit.)
3) On the flip side, the compiler can't know, in the CRTP class, that the only class ever to derive from it will be the one named by the Derived argument, because the language doesn't make such a guarantee.
4) The derived type can never be complete, or even partially complete, in the CRTP class body. That's just not how the compilation model of C++ works. The only way for the embedding class to provide things to the CRTP mixin that need to be known in the class definition and not just in the member definitions is via additional template arguments (possibly just one that is a traits class containing all the info). This is a major usability impediment.

To solve these problems, you would have to add the following to C++:
To solve 1) and 2), there would be a need to create a class template that, when derived from, implicitly gets the deriving class passed as a template argument. There must not be different way to pass this argument.
To solve 3), the compiler would have to know, in such a class, that the static type of `this` should be a pointer to that derived class.
To solve 4), there would have to be a way to delay instantiation of the base class until some point in the class definition, so that the base class can access at least parts of the deriving class.

I added these extensions. I call them mixins.
 
 
Well, this list is the "C++ standard proposals", if people didn't think it needs tweaks here and there, it would been deserted long ago.


Ah, you were talking about general C++ tweaks. I thought you meant something related to this particular problem domain.

Róbert Dávid

unread,
Aug 28, 2013, 8:02:38 AM8/28/13
to std-pr...@isocpp.org

That's new: In every single language out there, mixin is a type. While C++ does not have to follow the same path, I think it is a bad idea to have something that is behaved differently than what every programmer with experiences in other languages think. Please don't name it mixin, if this says like it.

It's a pack of code.


Soooo.. a macro? What's wrong with macros, besides the awkward "generally good idea not to use them" argument? How about this macro-based solution to the problem:

struct base {
 
virtual base& foo() = 0;
 
virtual base& bar() = 0;
};

#define MIXIN_FOO  \
 
int value; \
  __THIS_CLASS__
& foo() override;

#define MIXIN BAR \
 
void something(int); \
  __THIS_CLASS__
& bar() override { \
    something
(value); \

   
return *this; \
 
}

struct derived : public base
{

  MIXIN_FOO
  MIXIN_BAR
  value
= 5; //Meh - improvement area.
};


Regards, Robert

corn...@google.com

unread,
Aug 28, 2013, 8:07:11 AM8/28/13
to std-pr...@isocpp.org


On Wednesday, August 28, 2013 1:21:09 PM UTC+2, David Krauss wrote:
Really what you're describing is another form of inheritance. Rather than being a superclass or subclass, the mixin is a peer of the target.

Kind of, but not really, because a mixin is not a type. It's a collection of declarations and definitions to be injected into a real type.
 

The tricky part is deciding the relative order of declaration and initialization of the mixin members. C++11 is more sensitive than C++03 was to the declaration order of class members, because we have decltype() now. You could define the members at the using declaration, but this is a potential source of errors. (Unless you intended this, I'm not sure why you made it a using declaration rather than a base specifier.)

This is exactly what I intended. It's a potential source of errors, but it's also the most useful way of doing it, because it means the mixin can use some stuff from the embedder, and some thiings in the embedder can use the stuff in the mixin.
 

Some new syntax would be required to run the constructor of the mixin. It would be odd to mention a name from a using declaration in a constructor mem-initializer.

It's not a using declaration. It's a using mixin directive. ;-)
Yes, mixins can have constructors and destructors so that they can maintain their own invariants. And yes, I fully intend them to be called from the initializer list of the embedding class, using the mixin's name, mingled with the member variables of the class. I don't see why that's unintuitive, and especially not how new syntax would be any better.
 

Recently I suggested inferring member declarations from a concept applied to a template parameter used as a base class. A name that is required to exist doesn't really need to be considered type-dependent. Applied to an incomplete class, the principle could help bridge the gap that seems to be causing confusion in the above posts. Not to make a blanket judgment about this proposal, but CRTP can probably be improved by such relatively minor changes.
 
Using concepts on the parameter of a CRTP base - interesting idea. I'm not sure how concept checks would work for incomplete types, though.

Daniel Krügler

unread,
Aug 28, 2013, 8:08:01 AM8/28/13
to std-pr...@isocpp.org
2013/8/28 Róbert Dávid <lrd...@gmail.com>:
>
>> It's a pack of code.
>
> Soooo.. a macro?

I don't think that the proposed mixins are comparable with macros,
especially I would expect that they have C++ scope and naming rules.

> What's wrong with macros,

I could name a lot of them, but this time I just quote Sebastian from
his original message:

<quote>
The macro expands to the declaration of the two special members above, and in
some cases includes the access specifier. It has the following disadvantages:
- Uses the preprocessor.
- Repeats the class name.
- Changes the access specifier. OR Must be placed in private section.
</quote>

I'm not at all convinced that macros are an equivalent solution and I
would rather prefer to stay away from it, where this is possible.

- Daniel

Ville Voutilainen

unread,
Aug 28, 2013, 8:12:53 AM8/28/13
to std-pr...@isocpp.org
On 28 August 2013 15:02, Róbert Dávid <lrd...@gmail.com> wrote:
It's a pack of code.


Soooo.. a macro? What's wrong with macros, besides the awkward "generally good idea not to use them" argument? How about this macro-based solution to the problem:


Seriously? What's really wrong with macros is that they don't obey scopes, and error reporting when you make a mistake
in a macro definition is rather dismal. Debugging macro-heavy code can also be rather frustratingly hard. The
"generally good idea not to use them" is not just a random statement, it's based on the downsides of macros,
and it's not just grandstanding from the top of a high horse.

Róbert Dávid

unread,
Aug 28, 2013, 8:30:21 AM8/28/13
to std-pr...@isocpp.org

The macro expands to the declaration of the two special members above, and in
some cases includes the access specifier. It has the following disadvantages:
- Uses the preprocessor.
Preprocessor is part of C++. What's wrong with using a C++ feature? Yes, the preprocessor is bad. Can't we improve it?

- Repeats the class name.
Can be fixed with a __THIS_CLASS__-ish macro, the same way there is __FUNCTION__ or __PRETTY_FUNCTION__ in some implementations.

- Changes the access specifier. OR Must be placed in private section.
Probably can be fixed also.
 
I'm not at all convinced that macros are an equivalent solution and I
would rather prefer to stay away from it, where this is possible.

But they are equal to the "just a bunch of code" mixins. Obviously then they are not that.

Regards, Robert

corn...@google.com

unread,
Aug 28, 2013, 8:30:47 AM8/28/13
to std-pr...@isocpp.org


On Wednesday, August 28, 2013 2:02:38 PM UTC+2, Róbert Dávid wrote:

That's new: In every single language out there, mixin is a type. While C++ does not have to follow the same path, I think it is a bad idea to have something that is behaved differently than what every programmer with experiences in other languages think. Please don't name it mixin, if this says like it.

D's template mixins are not types. (They are very close to macros.)
Scala has mixins, but calls them traits.
PHP has what I want, but calls it traits.
Ruby's modules provide the same functionality, but it's referred to as mixin functionality.
Rust has traits, which are like interfaces, but mostly used for bounds in generics.

I could call the new feature "traits", but that name is already used by the standard library (iterator_traits, char_traits), and reusing it would be far more confusing than taking the already-muddled name mixins.
 

It's a pack of code.


Soooo.. a macro? What's wrong with macros, besides the awkward "generally good idea not to use them" argument?

Failure to integrate into the language. Failure to respect namespaces. Failure to understand templates passed as arguments (have you ever found the , between your template arguments being interpreted as separating your macro arguments?). Failure to provide decent debugger support on many platforms. Need I go on?
 
How about this macro-based solution to the problem:

struct base {
 
virtual base& foo() = 0;
 
virtual base& bar() = 0;
};

#define MIXIN_FOO  \

Argh, line continuations! Completely different from the rest of C++?
 

 
int value; \
  __THIS_CLASS__
& foo() override;

What if value is not supposed to be public? What about foo? Where does __THIS_CLASS__ come from?

struct derived : public base
{
  MIXIN_FOO
  MIXIN_BAR

What is the active access specifier here?

Macros are a hack. Every use of macros indicates a place where the core language is lacking.

Klaim - Joël Lamotte

unread,
Aug 28, 2013, 8:35:24 AM8/28/13
to std-pr...@isocpp.org
Another question:
would mixin composition be allowed?

mixin K
{
    using mixin U;
    using mixin W;
};


Róbert Dávid

unread,
Aug 28, 2013, 8:44:01 AM8/28/13
to std-pr...@isocpp.org, corn...@google.com

Macros are part of the language. It will not go away. We have to live with this fact.
But with improvements (sorry, but everyone seem to miss that this is my point) it could also work in the place of mixins. Same way as MI / CRTP could. Either way, with "small" standard changes you could have what you need (with different syntax), and the language doesn't need an extra ~hundred pages describing every single current feature's interaction with the new mixin feature.

Regards, Robert

Maurice Bos

unread,
Aug 28, 2013, 8:44:42 AM8/28/13
to std-pr...@isocpp.org



2013/8/28 Róbert Dávid <lrd...@gmail.com>


Can be fixed with a __THIS_CLASS__-ish macro, the same way there is __FUNCTION__ or __PRETTY_FUNCTION__ in some implementations.



__func__ and __PRETTY_FUNCTION__ are 'magic' variables of const char array types, they are not macro's. The preprocessor has nothing to do with these two variables.

corn...@google.com

unread,
Aug 28, 2013, 8:52:11 AM8/28/13
to std-pr...@isocpp.org
Yes, as stated in my proposal:

corn...@google.com

unread,
Aug 28, 2013, 8:59:47 AM8/28/13
to std-pr...@isocpp.org, corn...@google.com
On Wednesday, August 28, 2013 2:44:01 PM UTC+2, Róbert Dávid wrote:

Macros are a hack. Every use of macros indicates a place where the core language is lacking.


Macros are part of the language. It will not go away. We have to live with this fact.

But that doesn't mean we have to celebrate it. Inline functions, real constants, templates, now constexpr functions, are all replacing uses of macros. Attributes replace pragmas to some extent. Modules are in development to subsume/replace/obsolete includes. We cannot ever get rid of the preprocessor, but we want to relegate it to exotic uses and backward compatibility.
If you don't think this is a good goal to have, you are of course entitled to that opinion, but I think you won't find many like-minded people in the C++ community, much less the standard committee.
 
But with improvements (sorry, but everyone seem to miss that this is my point) it could also work in the place of mixins.

No, I get it. But the preprocessor is fundamentally, irrevocably at a completely different level than the rest of the language - it has its own rules about what a token is! There's just no place to *start* when you suggest improvements to the preprocessor to make it a viable way of routinely doing things.
 
Same way as MI / CRTP could.

Awaiting your reply to my earlier post.
 
Either way, with "small" standard changes you could have what you need (with different syntax), and the language doesn't need an extra ~hundred pages describing every single current feature's interaction with the new mixin feature.

I don't know why you put "small" in quotes. Maybe because you yourself don't believe they are actually small changes? To achieve what I want, you would have to mangle the current concept of inheritance beyond recognition, and if you do that, what is the point of using inheritance?
 

Róbert Dávid

unread,
Aug 28, 2013, 9:37:19 AM8/28/13
to std-pr...@isocpp.org, corn...@google.com


2013. augusztus 28., szerda 14:59:47 UTC+2 időpontban corn...@google.com a következőt írta:

I don't know why you put "small" in quotes.
 

There is no such thing as a small change in a standard. You cannot just add 3 lines into the standard text and done, you need to think over what is the implication of the change for a compiler author, how does it work well with other language features, and add text about how those features work if they encounter the new feature. My example of adding a __THIS_CLASS__ magic macro will probably not break much stuff, probably does not have to change a lot of other stuff, but I still not sure. I'm absolutely sure about adding the proposed mixin will wreak havoc among in almost every single clause of the language. It will be so complex you will (figuratively) never get your feature, while some current feature can be improved to fit, you might even get it in C++17.

That's why.

The CRTP question needs some time to answer, I'll get there when I have the chance.

Regards, Robert

Maurice Bos

unread,
Aug 28, 2013, 9:46:14 AM8/28/13
to std-pr...@isocpp.org
__THIS_CLASS__ cannot be a macro, for the same reason __func__ is not a macro. It could be a 'magic' typedef just like how __func__ is a 'magic' variable, but that has nothing to do with the preprocessor at all.


2013/8/28 Róbert Dávid <lrd...@gmail.com>

--
 
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

corn...@google.com

unread,
Aug 28, 2013, 9:55:13 AM8/28/13
to std-pr...@isocpp.org, corn...@google.com


On Wednesday, August 28, 2013 3:37:19 PM UTC+2, Róbert Dávid wrote:

I'm absolutely sure about adding the proposed mixin will wreak havoc among in almost every single clause of the language. It will be so complex you will (figuratively) never get your feature,

I am quite familiar with reading and implementing the standard. I disagree with your assessment. The feature is pretty well isolated for such a big thing. The most intrusive change is the issue of completeness of the embedding class when instantiating the mixin, and the lookup rules will be affected by the injected names depending on the exact resolution of the pending issues there, but that's not unexpected.

Dávid Róbert

unread,
Aug 28, 2013, 9:11:47 PM8/28/13
to std-pr...@isocpp.org
How should mixins behave with inheritance, is it "inheriting" the mixin (so if descendants are also "using" it), or is ends there, descendants just get the members like they were defined normally?

Consider:
mixin cloneable {
  cloneable
* clone() const { return new cloneable; }
};
struct Foo {
 
using mixin cloneable;
};
struct Bar : public Foo {
};

using A = decltype(Bar().clone());
Is type A equal to Foo* or Bar*? Is Bar cloneable?

Consider:
mixin noncopyable {
  noncopyable
(const noncopyable&) = delete;
};
struct Foo{
 
using mixin noncopyable;
};
struct Bar : public Foo {
  Bar(const Bar&) : Foo() {}
}
Is Bar noncopyable (conflicting with the copy constructor definition, making Bar ill-formed)?

Regards, Robert

corn...@google.com

unread,
Aug 29, 2013, 5:38:11 AM8/29/13
to std-pr...@isocpp.org


On Thursday, August 29, 2013 3:11:47 AM UTC+2, Róbert Dávid wrote:
How should mixins behave with inheritance, is it "inheriting" the mixin (so if descendants are also "using" it), or is ends there, descendants just get the members like they were defined normally?

They just get the members. Anything else would be extremely confusing.
 

Consider:
mixin cloneable {
  cloneable
* clone() const { return new cloneable; }
};
struct Foo {
 
using mixin cloneable;
};
struct Bar : public Foo {
};

using A = decltype(Bar().clone());
Is type A equal to Foo* or Bar*? Is Bar cloneable?

Bar does not have its own override of clone(). A is Foo*. Bar is still "cloneable" in the sense that you can call clone() on it, but it will do the wrong thing.
 

Consider:
mixin noncopyable {
  noncopyable
(const noncopyable&) = delete;
};
struct Foo{
 
using mixin noncopyable;
};
struct Bar : public Foo {
  Bar(const Bar&) : Foo() {}
}
Is Bar noncopyable (conflicting with the copy constructor definition, making Bar ill-formed)?


Bar is well-formed and copyable.
 
Sebastian

Tony V E

unread,
Aug 29, 2013, 7:25:27 PM8/29/13
to std-pr...@isocpp.org



On Tue, Aug 27, 2013 at 5:14 PM, Sebastian Redl <wasti...@gmx.net> wrote:


=== Mixins (Class Extension Blocks) for C++ ===





The idea of making it easier to implement > in terms of <, etc comes up often in the Committee.  ie operator>() = default;  (or some other syntax).  I suspect it will eventually happen.  Bjarne seems interested (IMO at least).

That would be nice, but you might still need to do that for each operator.  I'd prefer one line "mixin std::operators;" or something like that.

I think a nice general mixin solution would be better than trying to solve all the little cases.

Tony

stackm...@hotmail.com

unread,
Aug 29, 2013, 8:59:59 PM8/29/13
to std-pr...@isocpp.org
I very much like this idea. Two things:
  • There has been at least a thread to propose decltype(class) to mean "the type of the current class". This is what __THIS_CLASS__ is supposed to be, with a nice syntax imo.
  • I've had an idea in my head for a long time that seems to be much more flexible than yours. I call it "code generators".
    The best way to explain this feature is probably using an example.

codegen noncopyable()
{
    emit
    {
        decltype(class)(decltype(class) const&) = delete;
        decltype(class)& operator = (decltype(class) const&) = delete;
    }
}
This thing is not just a macro with better syntax, it is a fully-fledged constexpr function that can have compiletime-loops and use compiletime reflection to generate code. The only difference to a regular constexpr function is that it does not have a return type and instead emits code.

Let's see how this can be used:

struct Foo
{
    $noncopyable() // special call syntax could be using the $-sign or some other currently unused character
};
Another idea I had is a special "operator emit" that can be overloaded by classes to allow us to carry code around statefully. I have not yet put enough thought into this though.


David Krauss

unread,
Aug 30, 2013, 2:19:57 AM8/30/13
to std-pr...@isocpp.org, corn...@google.com

On Wednesday, August 28, 2013 8:07:11 PM UTC+8, corn...@google.com wrote:

On Wednesday, August 28, 2013 1:21:09 PM UTC+2, David Krauss wrote:
Some new syntax would be required to run the constructor of the mixin. It would be odd to mention a name from a using declaration in a constructor mem-initializer.

It's not a using declaration. It's a using mixin directive. ;-)
 
Yes, mixins can have constructors and destructors so that they can maintain their own invariants. And yes, I fully intend them to be called from the initializer list of the embedding class, using the mixin's name, mingled with the member variables of the class. I don't see why that's unintuitive, and especially not how new syntax would be any better.

Often the invariants for members are not established by the first line of the constructor body. A mixin depending on some functionality in the host class would expect invariants for the host members its constructor accesses. The host class would in the general case need to call the mixin's constructor from its body. The same actually goes for destructors: the host destructor needs to relinquish the mixin at some point in its execution, not before beginning or after ending.

Maybe I'm making something out of nothing. There can always be initialize and finalize methods in addition to the constructor and destructor. Moving the calls of the constructor and destructor would wreak havoc with object lifetimes.

On the other hand, being able to defer initialization of a member whose constructor arguments require more preparation than can be accomplished in the mem-initializer-list would work around a longstanding issue. All we really need after all is to make UB use before initialization.
 
Recently I suggested inferring member declarations from a concept applied to a template parameter used as a base class. A name that is required to exist doesn't really need to be considered type-dependent. Applied to an incomplete class, the principle could help bridge the gap that seems to be causing confusion in the above posts. Not to make a blanket judgment about this proposal, but CRTP can probably be improved by such relatively minor changes.
 
Using concepts on the parameter of a CRTP base - interesting idea. I'm not sure how concept checks would work for incomplete types, though.

Concepts are applicable to any template parameter, and tolerating an incomplete argument is generally considered to be a good thing. There should be a modifier, applicable to any concept parameter declaration, that defers the check until an incomplete class type is completed. (I just figured this out now, should start a new thread. Thanks for the impetus!)

corn...@google.com

unread,
Aug 30, 2013, 8:55:29 AM8/30/13
to std-pr...@isocpp.org, corn...@google.com


On Friday, August 30, 2013 8:19:57 AM UTC+2, David Krauss wrote:

On Wednesday, August 28, 2013 8:07:11 PM UTC+8, corn...@google.com wrote:
 
Yes, mixins can have constructors and destructors so that they can maintain their own invariants. And yes, I fully intend them to be called from the initializer list of the embedding class, using the mixin's name, mingled with the member variables of the class. I don't see why that's unintuitive, and especially not how new syntax would be any better.

Often the invariants for members are not established by the first line of the constructor body. A mixin depending on some functionality in the host class would expect invariants for the host members its constructor accesses.

This is a good point, but I think it is the exception rather than the rule.
 
The host class would in the general case need to call the mixin's constructor from its body. The same actually goes for destructors: the host destructor needs to relinquish the mixin at some point in its execution, not before beginning or after ending.

Maybe I'm making something out of nothing. There can always be initialize and finalize methods in addition to the constructor and destructor. Moving the calls of the constructor and destructor would wreak havoc with object lifetimes.

I have no idea how common this situation would be. My gut feeling says "very uncommon, initialize and finalize are fine as workarounds", but I don't know how much of that is wishful thinking.
 

On the other hand, being able to defer initialization of a member whose constructor arguments require more preparation than can be accomplished in the mem-initializer-list would work around a longstanding issue. All we really need after all is to make UB use before initialization.

No, that's not all. Consider:

class A {
  B b;
  C c;
public:
  A(int x, int y)
    : b(defer), // let's make this explicit
      c(x) // could throw
  {
    int z = foobar(x); // could also throw
    b.B(y, z);
    c.froblize(b); // could also throw
  }
};

Keeping the order of destruction correct in the face of such a feature would be non-trivial.

Vicente J. Botet Escriba

unread,
Aug 31, 2013, 2:59:19 AM8/31/13
to std-pr...@isocpp.org
Le 29/08/13 11:38, corn...@google.com a écrit :


On Thursday, August 29, 2013 3:11:47 AM UTC+2, Róbert Dávid wrote:
How should mixins behave with inheritance, is it "inheriting" the mixin (so if descendants are also "using" it), or is ends there, descendants just get the members like they were defined normally?

They just get the members. Anything else would be extremely confusing.
I agree, even if for the example below it would be an interesting approach, as cloneable must be repeated for each derived class.  
 

Consider:
mixin cloneable {
  cloneable
* clone() const { return new cloneable; }
};
struct Foo {
 
using mixin cloneable;
};
struct Bar : public Foo {
};

using A = decltype(Bar().clone());
Is type A equal to Foo* or Bar*? Is Bar cloneable?

Bar does not have its own override of clone(). A is Foo*. Bar is still "cloneable" in the sense that you can call clone() on it, but it will do the wrong thing.
Note that the same occurs if mixins are implemented using CRTP.

 

Consider:
mixin noncopyable {
  noncopyable
(const noncopyable&) = delete;
};
struct Foo{
 
using mixin noncopyable;
};
struct Bar : public Foo {
  Bar(const Bar&) : Foo() {}
}
Is Bar noncopyable (conflicting with the copy constructor definition, making Bar ill-formed)?


Bar is well-formed and copyable.

This seems counter intuitive. If Foo is not copyable, Bar canot be copyable.

Best,
Vicente

Vicente J. Botet Escriba

unread,
Aug 31, 2013, 3:50:25 AM8/31/13
to std-pr...@isocpp.org
Le 27/08/13 23:14, Sebastian Redl a écrit :
The ability to inject additional code into a class is something that I have repeatedly missed. Aside from a number of minor uses, I've twice found myself writing a library that would really have benefited from such a feature.

Since someone mentioned this feature a few days back, I thought I'd write up my thoughts on the matter and post them here to gauge interest and gather comments. Preliminary proposal below.



=== Mixins (Class Extension Blocks) for C++ ===

--- Purpose ---
Create a solution for injecting repetitive code into classes that has intuitive
syntax, doesn't use the preprocessor, and lacks the drawbacks of the CRTP.

--- Background ---
There's often a need for classes to contain somewhat repetitive code. For the
purpose of this document, we'll go with three motivating examples, in
increasing complexity.

Hi,

I agree that we need a way to inject repetitive code into a class. I'm not against not for your proposal. I would like just have more insight on the design rationale and why not try to help you to make a better proposal.

<snip>

Example 2: Repetitive Operators (Boost.Operators, Boost.Iterator)
If I want to define my own smart pointer, here's what I have to do:
template <typename T>
class my_ptr {
  // Custom storage logic.
  T* raw;
public:
  // Custom construction and destruction logic.

  T* get() const {
    // Custom access logic.
    return raw;
  }

  // All these can be defined in terms of get():
  T& operator *() const { return *get(); }
  T* operator ->() const { return get(); }
  // This was worse in C++03, when the safe-bool idiom had to be used.
  explicit operator bool() const { return get() != nullptr; }
  bool operator !() const { return get() == nullptr; }
};

Again, one could define a macro to encapsulate these operations, or a base
class. However, the base class solution has the problem that it needs to access
the get() function in the derived class. There are two possible ways to deal
with this.

<snip<

The second way is to use the Curiously Recurring Template Pattern:
template <typename Derived, typename T>
class smart_ptr_base {
  const Derived& self() const { return *static_case<const Derived*>(this); }
public:
  T& operator *() const { return *self().get(); }
  // etc.
};
template <typename T>
class my_ptr : public smart_ptr_base<my_ptr<T>, T> {
  T* get() const { return raw; }
};

The drawbacks of this solution are:
- The CRTP introduces its own boilerplate (the self() function).
- The CRTP's workings are unintuitive to those introduced to it - there's a
  reason it's called "curiously" recurring. In particular, the fact that
  Derived is an incomplete type in the body of the CRTP class is a common
  stumbling block, and the reason T must be passed along in the above example
  instead of determined by examining Derived (e.g. to look at a nested typedef).
  Function type deduction in C++14 can help in some cases, but not all.
- The class name must be repeated, including all its template arguments - the
  injected-class-name is not yet visible in the base specification.
- The interface that the CRTP base uses from the derived class must either be
  public, or there must be some friendship between the classes. Specifying the
  entire base class in a friend declaration can be annoying, and friending a
  type alias wasn't possible before C++11, which led to workarounds such as
  iterator_core_access (from Boost.Iterator).

I have used an alternative approach for mixins. A mixin is a metafunction having a Derived and a Base class. There is a base mixin that defines the self function and that has no Base parameter on the metafunction.

template <typename Base>
struct self_mixin {
  
template <typename Derived>
  class type
: public Base
   {
  
public:
    using Base::Base;
  protected:
    typedef Derived derived_type;
    const Derived& self() const { return *static_cast<const Derived*>(this); }
    Derived& self() { return *static_cast<Derived*>(this); }
  };
};


template <typename T>
class smart_ptr_mixin 
{
  template <typename Derived, typename Base>
  class type : public Base {
  public:
    using Base::Base;
  public:
    T& operator *() const { return *self().get(); }
    // etc.
  };
};


The use of these mixins is done as

template <typename T>
class my_ptr : public mixins<
my_ptr<T>, self_mixin<>, smart_ptr_mixin<T> >
{
public:
  T* get() const { return raw; }
  // ...
};



mixins has as parameter the current class, and the list of mixins starting from the base one.


We could make define a MIXIN macro so that


template <typename T>
MIXIN(smart_ptr_mixin) 
{
public:
  T& operator *() const { return *self().get(); }
  // etc.
};

is equivalent to


template <typename T>
class smart_ptr_mixin 
{
 
template <typename Derived, typename Base>
  class type : public Base {
  public:
    using Base::Base;
    friend Derived;
  public:
    T& operator *() const { return *self().get(); }
    // etc.
  };
};

This approach solve some of the drawbacks you mention, while not all.
The noise is in boldbace




--- Proposed Solution ---
Introduce a new code construct, the "mixin". A mixin is similar to a class, but
is not a type by itself. Instead, a mixin is embedded in (mixed into) a class;
its members become members of the class. A mixin is implicitly templated on the
type that embeds it, but can in addition have further template parameters. A
mixin is embedded in a class with a "using mixin" directive.

Example 1: Non-Copyable
Here's a non-copyable mixin:

mixin noncopyable {
  noncopyable(const noncopyable&) = delete;
  noncopyable& operator =(const noncopyable&) = delete;
}
class foo {
  using mixin noncopyable;
};

Here, the compiler will fail to generate the copy functions for foo, because
they would have to call the mixin's copy functions, which are deleted. The mixin
acts like a data member here, including the order of construction (i.e. when
data members and mixins are mixed, the constructors are called in the order of
declaration).

Does making mixins act like data member makes then increase the size of the class?
Have you considered to see them as part of the inheritance hierarchy?

class foo : public mixin X
{
};

Example 2: Repetitive Operators
Here's the smart_ptr mixin:

mixin smart_ptr {
public:
  // Could use decltype(auto) in C++14, but in some cases we can't, e.g. when
  // we want to use SFINAE tricks on some overloads.
  auto operator *() const -> decltype(*this->get()) { return *this->get(); }
  auto operator ->() const -> decltype(this->get()) { return this->get(); }
  explicit operator bool() const { return this->get() != nullptr; }
  bool operator !() const { return this->get() == nullptr; }
}
template <typename T>
class my_ptr {
public:
  T* get() const { return raw; }
  using mixin smart_ptr;
};

To make this work, we need rules about the access to the embedding class from
the mixin.
Since the mixin is a template, the type of its 'this' pointer is dependent.
The syntax for acessing members is the same as that for access to members of
dependent base classes: use 'this->' to make the expression dependent and delay
lookup until instantiation time.
Have you considered adding a self keyword instead of using this?
When the mixin is instantiated, the completeness of the embedding class is
treated exactly as if the mixin's code was directly embedded into the class,
i.e. members prior to the mixin directive are visible, those after are not, and
all the usual rules for ambiguity and changing meanings apply.
Mixins can contain access declarations. Their members have the more restricted
access of the one they have in the mixin and the one the mixin directive is
under. (POD: Just ignore the latter?)
Mixins can access all members of the embedding class, even private ones.

Example 3: Polymorphic Cloning
Here's the cloneable mixin:

mixin cloneable {
public:
  decltype(mixin)* clone() const override { return new decltype(mixin)(*this); }
}
class foo : public base {
public:
  using mixin cloneable;
};

Functions in the mixin override functions the embedding class inherited.
The 'decltype(mixin)' construct names the embedding class. This is to save on
new keywords.




Mixins can contain every kind of declaration that classes can, including inner
types, data members, and more mixin directives. Mixins cannot have base classes.
(POD: Should they be able to? The bases could be appended to the list of bases
of the embedding class. What kind of problems could that cause?)

I don't see why the introduction of the last constraint is needed. With the CRTP model there is no such limitation

template <typename T>
class smart_ptr_mixin 
{
 
template <typename Derived, typename Base>
  class type : public Base, smart_ptr_base {
  public:
    using Base::Base;
    friend Derived;
  public:
    T& operator *() const { return *self().get(); }
    // etc.
  };
};


<snip>

On a side note, name conflicts can arise between the embedding class and mixins,
especially for nested types defined for utility, e.g. difference_type and
reference in the example above are defined in both the embedding class, and
the random access mixin. I believe that the best resolution rules are:
- Conflicting variables are an error, with the exception of static constants
  with known values, which get merged if the values are the same.
I wouldn't  consider this as an exception.
- Functions overload. If they cannot overload, it's an error.
The CRTP pattern allow to manage with this case as each mixin can relay on the base mixin. I see this is an advantage of the inheritance approach respect to the member approach.

For example, several mixins could define a trace function that use the base one and add something else

void trace() {
  this->base_type.trace();
  // ....
}
- Types are merged if they are the same type.

In addition, it might be useful to make it possible for mixins to have sections
that are not made visible to the embedding class (e.g. a "mixin:" access
specifier), although I am hesitant to really do this, because I can see a
pattern developing where the entire class body is always put in a mixin, and a
mixin: specifier is used to create "truly hidden" private sections.
Why using private as for class is not enough? What am I missing?

Best,
Vicente

Vicente J. Botet Escriba

unread,
Aug 31, 2013, 4:23:20 AM8/31/13
to std-pr...@isocpp.org
Le 28/08/13 02:54, Sean Middleditch a écrit :
On Tuesday, August 27, 2013 4:59:34 PM UTC-7, Róbert Dávid wrote:

That is an incredibly simplistic example of the CRTP mixin pattern.  Try a class that wants to use two mixins which each partially implement some of the polymorphic interface of a base.  It gets unwieldly, quickly.
Could you show a concrete example and how the proposed mixin feature would help?
 


And then there's the weird recursive situations, which granted are very exceptional in a good design, but I've seen come up several time.  Example:

   struct base {
     virtual base& foo() = 0;
     virtual base& bar() = 0;
   };

   template <class Derived, class Base>
   struct mixin_foo : public Base {
     int value;
     Derived& foo() override;
   };

   template <class Derived, class Base>
   struct mixin_bar : public Base {
     void something(int);
     Derived& bar() override {
       something(static_cast<Derived&>(*this).value);
       return *this;
     }
   };

   struct derived : publix mixin_foo<derived, mixin_bar<mixin_foo<derived, ???>, base>>
   {
      int value = 5; // note that mixin_bar wants to use mixin_foo's value, not derived's value
   };

Shouldn't this be

     Derived& bar() override {
       something(this->Base.value);
       return *this;
     }

and

   struct derived : publix mixin_bar<derived, mixin_foo<derived, base>>

?
Oppose this to a mixin solution:

   struct base {
     virtual base& foo() = 0;
     virtual base& foo() = 0;
   };

There's no way to realistically fill in the ??? part as mixin_bar's Derived type is itself dependent on mixin_bar. Again, it's a weird case, and every time I've seen it myself I've found other (arguably much better) ways to do what I wanted, but it is a general pattern that C++ multiple inheritance and CRTP are not an alternative to mixins.  You can't _compose mixins_ with CRTP.
    
Sorry I missed the mixin solution?

Best,
Vicente

Vicente J. Botet Escriba

unread,
Aug 31, 2013, 4:24:59 AM8/31/13
to std-pr...@isocpp.org
Le 28/08/13 02:59, Sean Middleditch a écrit :
On Tuesday, August 27, 2013 5:54:43 PM UTC-7, Sean Middleditch wrote:

Oppose this to a mixin solution:

   struct base {
     virtual base& foo() = 0;
     virtual base& foo() = 0;
   };

And I got distracted and cut short writing up that mixin example.  

   struct base {
     virtual base& foo() = 0;
     virtual base& bar() = 0;
   };

   struct mixin_foo mixin {
     int value;
     auto decltype(*this) foo();
   };

   struct mixin_bar mixin {
     void something(int);
     auto bar() {
       something(this->value);
       return *this;
     }
   };

   struct derived : public base
   {
      using mixin mixin_foo;
      using mixin mixin_bar { using mixin_foo::value; } // sample syntax
      int value = 5;
   };

I'm not super fond of the syntax there, but the idea is illustrated as well as it can for such a silly example I think.

Oh, I've got it now. I don't see too much difference between the CRTP and the proposed mixin approach.

Vicente

corn...@google.com

unread,
Sep 2, 2013, 10:24:26 AM9/2/13
to std-pr...@isocpp.org
Why? You just explicitly defined that Bar's notion of copying is to default-construct the Foo part of the object. If you explicitly define the copy constructor for a class, that class is copyable; everything else would be highly counter-intuitive.
 

corn...@google.com

unread,
Sep 2, 2013, 10:51:21 AM9/2/13
to std-pr...@isocpp.org


On Saturday, August 31, 2013 9:50:25 AM UTC+2, Vicente J. Botet Escriba wrote:
Hi,

I agree that we need a way to inject repetitive code into a class. I'm not against not for your proposal. I would like just have more insight on the design rationale and why not try to help you to make a better proposal.


Hi Vicente,

Thanks for all the feedback.
 
<snip>

I have used an alternative approach for mixins. A mixin is a metafunction having a Derived and a Base class. There is a base mixin that defines the self function and that has no Base parameter on the metafunction.

template <typename Base>
struct self_mixin {
  
template <typename Derived>
  class type
: public Base
   {
  
public:
    using Base::Base;
  protected:
    typedef Derived derived_type;
    const Derived& self() const { return *static_cast<const Derived*>(this); }
    Derived& self() { return *static_cast<Derived*>(this); }
  };
};


template <typename T>
class smart_ptr_mixin 
{
  template <typename Derived, typename Base>
  class type : public Base {
  public:
    using Base::Base;
  public:
    T& operator *() const { return *self().get(); }

Nit: must be 'return *this->self().get();'
 
    // etc.
  };
};


The use of these mixins is done as

template <typename T>
class my_ptr : public mixins<
my_ptr<T>, self_mixin<>, smart_ptr_mixin<T> >
{
public:
  T* get() const { return raw; }
  // ...
};



mixins has as parameter the current class, and the list of mixins starting from the base one.

I have actually developed a very similar system at one point, although it was C++03 and bound to one specific use case (which fixed the constructors and put a bound on the number of possible mixins, otherwise it would have been just horrible). It was still incredibly awkward to use, especially since I needed it in the public interface of the library I was developing at the time; people writing additional components within my framework would have had to use it. It was so bad that I scrapped the design completely.

Nested templates are simply ugly, and that's without trying to define some of the mixin's methods out-of-line; then you get to multiple template parameter lists, which I bet 90% of C++ programmers have never seen in production code, much less written.
 
We could make define a MIXIN macro so that


template <typename T>
MIXIN(smart_ptr_mixin) 
{
public:
  T& operator *() const { return *self().get(); }
  // etc.
};

is equivalent to


template <typename T>
class smart_ptr_mixin 
{
 
template <typename Derived, typename Base>
  class type : public Base {
  public:
    using Base::Base;
    friend Derived;
  public:
    T& operator *() const { return *self().get(); }
    // etc.
  };
};

No, you actually can't. You can't generate the second closing brace from the macro. You could define the macro to expand to something like

class NAME {
  template <typename Derived, typename Base> class type;
};
template <typename Derived, typename Base> class NAME::type /* user continues here */

but that breaks for mixin templates, which require you to give the template parameter list and argument list forms to the macro, and then you run into the usual problems with commas in angle brackets in macro arguments, and even if you manage to solve it, it's one gigantic mess.

 

This approach solve some of the drawbacks you mention, while not all.

I don't really thinks it solves any of the drawbacks. The boilerplate may be somewhat reduced, if you manage to write the macro, but all the other points in my list remain unaffected.
 
Does making mixins act like data member makes then increase the size of the class?
Have you considered to see them as part of the inheritance hierarchy?

Mixins don't act like data members for any purpose but construction/destruction.
 

class foo : public mixin X
{
};

This runs into the problems I mentioned about the completeness of foo within the mixin.
 
Since the mixin is a template, the type of its 'this' pointer is dependent.
The syntax for acessing members is the same as that for access to members of
dependent base classes: use 'this->' to make the expression dependent and delay
lookup until instantiation time.
Have you considered adding a self keyword instead of using this?

For a moment, but I don't see the point. 'self' is completely impossible to add, since it is widely used as a variable/function name, and the new use would be in a context where a variable name can appear. If you know any other conveniently short and logical words that aren't already in wide use in expression context, I'd love to hear about them, though.
 

Mixins can contain every kind of declaration that classes can, including inner
types, data members, and more mixin directives. Mixins cannot have base classes.
(POD: Should they be able to? The bases could be appended to the list of bases
of the embedding class. What kind of problems could that cause?)

I don't see why the introduction of the last constraint is needed. With the CRTP model there is no such limitation

The constraint isn't *needed*, it's just something that I didn't want to think about too hard. I would have to decide on the order of initialization, and from a compiler writer viewpoint, I'm not sure what it would mean to change the inheritance graph of a class in the middle of the body.
 
- Functions overload. If they cannot overload, it's an error.
The CRTP pattern allow to manage with this case as each mixin can relay on the base mixin. I see this is an advantage of the inheritance approach respect to the member approach.

For example, several mixins could define a trace function that use the base one and add something else

void trace() {
  this->base_type.trace();
  // ....
}

This is a good point. Relaying calls from one mixin to another is a use case I haven't considered so far. I have no good solution for this at the moment.
 
In addition, it might be useful to make it possible for mixins to have sections
that are not made visible to the embedding class (e.g. a "mixin:" access
specifier), although I am hesitant to really do this, because I can see a
pattern developing where the entire class body is always put in a mixin, and a
mixin: specifier is used to create "truly hidden" private sections.
Why using private as for class is not enough? What am I missing?

In the base class model, conflicting names just hide each other; they are not by themselves an error. But going with the model of inheriting conflicting names from multiple bases might be the best model for what I want to achieve after all. 

Vicente J. Botet Escriba

unread,
Sep 2, 2013, 1:22:22 PM9/2/13
to std-pr...@isocpp.org
Le 02/09/13 16:24, corn...@google.com a écrit :
Agreed. I miss that the default Foo() constructor was called.

Vicente

Vicente J. Botet Escriba

unread,
Sep 2, 2013, 1:22:37 PM9/2/13
to std-pr...@isocpp.org
Le 02/09/13 16:51, corn...@google.com a écrit :
Hrr, you are right. this-> is needed inside the template.

 
    // etc.
  };
};


The use of these mixins is done as

template <typename T>
class my_ptr : public mixins<
my_ptr<T>, self_mixin<>, smart_ptr_mixin<T> >
{
public:
  T* get() const { return raw; }
  // ...
};



mixins has as parameter the current class, and the list of mixins starting from the base one.

I have actually developed a very similar system at one point, although it was C++03 and bound to one specific use case (which fixed the constructors and put a bound on the number of possible mixins, otherwise it would have been just horrible). It was still incredibly awkward to use, especially since I needed it in the public interface of the library I was developing at the time; people writing additional components within my framework would have had to use it. It was so bad that I scrapped the design completely.

Nested templates are simply ugly, and that's without trying to define some of the mixin's methods out-of-line; then you get to multiple template parameter lists, which I bet 90% of C++ programmers have never seen in production code, much less written.
Why would you need to define the mixin's methods out-of-line?
 
We could make define a MIXIN macro so that


template <typename T>
MIXIN(smart_ptr_mixin) 
{
public:
  T& operator *() const { return *self().get(); }
  // etc.
};

is equivalent to


template <typename T>
class smart_ptr_mixin 
{
 
template <typename Derived, typename Base>
  class type : public Base {
  public:
    using Base::Base;
    friend Derived;
  public:
    T& operator *() const { return *self().get(); }
    // etc.
  };
};

No, you actually can't. You can't generate the second closing brace from the macro.
Right. You can try then with

template <typename T>
MIXIN_BEGIN(smart_ptr_mixin) 
public:
  T& operator *() const { return *self().get(); }
  // etc.
MIXIN_END;

I agree that don't having the braces is ugly.

Alternatively you can do

template <typename T>
class
smart_ptr_mixin
{
  MIXIN_BEGIN;
 
public:

  T& operator *() const { return *self().get(); }
  // etc.
  MIXIN_END;
}
;

that could expand to

template <typename T>
class smart_ptr_mixin 
{
 
template <typename Derived, typename Base>
  class type : public Base {
  public:
    using Base::Base;
    typedef Derived derived_type;
    const Derived& self() const { return *static_cast<const Derived*>(this); }
    Derived& self() { return *static_cast<Derived*>(this); }
  public:
    T& operator *() const { return *self().get(); }
    // etc.
  };
};

So that you can use self() directly.
You could define the macro to expand to something like

class NAME {
  template <typename Derived, typename Base> class type;
};
template <typename Derived, typename Base> class NAME::type /* user continues here */

but that breaks for mixin templates, which require you to give the template parameter list and argument list forms to the macro, and then you run into the usual problems with commas in angle brackets in macro arguments, and even if you manage to solve it, it's one gigantic mess.

 

This approach solve some of the drawbacks you mention, while not all.

I don't really thinks it solves any of the drawbacks. The boilerplate may be somewhat reduced, if you manage to write the macro, but all the other points in my list remain unaffected.
I'm not proposing these macros. I'm just seen how close a mixin implementation (compiler) to a CRTP model it could be. The advantage is that the model is well known, and so the new feature will be only syntactic sugar, which clearly is needed.
 
Does making mixins act like data member makes then increase the size of the class?
Have you considered to see them as part of the inheritance hierarchy?

Mixins don't act like data members for any purpose but construction/destruction.
OK.

 

class foo : public mixin X
{
};

This runs into the problems I mentioned about the completeness of foo within the mixin.
I don't see this as a problem, but a future of mixins. A mixin has only sense once instantiated.

 
Since the mixin is a template, the type of its 'this' pointer is dependent.
The syntax for acessing members is the same as that for access to members of
dependent base classes: use 'this->' to make the expression dependent and delay
lookup until instantiation time.
Have you considered adding a self keyword instead of using this?

For a moment, but I don't see the point. 'self' is completely impossible to add, since it is widely used as a variable/function name, and the new use would be in a context where a variable name can appear. If you know any other conveniently short and logical words that aren't already in wide use in expression context, I'd love to hear about them, though.
The keyword can be contextual.

 

Mixins can contain every kind of declaration that classes can, including inner
types, data members, and more mixin directives. Mixins cannot have base classes.
(POD: Should they be able to? The bases could be appended to the list of bases
of the embedding class. What kind of problems could that cause?)

I don't see why the introduction of the last constraint is needed. With the CRTP model there is no such limitation

The constraint isn't *needed*, it's just something that I didn't want to think about too hard. I would have to decide on the order of initialization, and from a compiler writer viewpoint, I'm not sure what it would mean to change the inheritance graph of a class in the middle of the body.
Ok.

 
- Functions overload. If they cannot overload, it's an error.
The CRTP pattern allow to manage with this case as each mixin can relay on the base mixin. I see this is an advantage of the inheritance approach respect to the member approach.

For example, several mixins could define a trace function that use the base one and add something else

void trace() {
  this->base_type.trace();
  // ....
}

This is a good point. Relaying calls from one mixin to another is a use case I haven't considered so far. I have no good solution for this at the moment.
The alternative CRTP model would allow it without any trouble.

 
In addition, it might be useful to make it possible for mixins to have sections
that are not made visible to the embedding class (e.g. a "mixin:" access
specifier), although I am hesitant to really do this, because I can see a
pattern developing where the entire class body is always put in a mixin, and a
mixin: specifier is used to create "truly hidden" private sections.
Why using private as for class is not enough? What am I missing?

In the base class model, conflicting names just hide each other; they are not by themselves an error. But going with the model of inheriting conflicting names from multiple bases might be the best model for what I want to achieve after all.
Sorry, I don't understand. Are you telling inheriting from multiple bases?

Best,
Vicente

corn...@google.com

unread,
Sep 3, 2013, 11:54:40 AM9/3/13
to std-pr...@isocpp.org


On Monday, September 2, 2013 7:22:37 PM UTC+2, Vicente J. Botet Escriba wrote:
Le 02/09/13 16:51, corn...@google.com a écrit :
Nested templates are simply ugly, and that's without trying to define some of the mixin's methods out-of-line; then you get to multiple template parameter lists, which I bet 90% of C++ programmers have never seen in production code, much less written.
Why would you need to define the mixin's methods out-of-line?

Every other construct in C++ allows out-of-line definition; why should it be impossible for mixins?
  

class foo : public mixin X
{
};

This runs into the problems I mentioned about the completeness of foo within the mixin.
I don't see this as a problem, but a future of mixins. A mixin has only sense once instantiated.

I don't understand what you mean by that. I want mixins to be able to refer to at least some members of the embedding class from the mixin body, not just the functions.
 
Have you considered adding a self keyword instead of using this?

For a moment, but I don't see the point. 'self' is completely impossible to add, since it is widely used as a variable/function name, and the new use would be in a context where a variable name can appear. If you know any other conveniently short and logical words that aren't already in wide use in expression context, I'd love to hear about them, though.
The keyword can be contextual.

No, it can't be. That's what I've been trying to say with "would be in a context where a variable name can appear". Contextual keywords only work if the new use for the keyword is in a context where no existing identifier could appear. For example, the 'final' and 'override' contextual keywords only appear after the class name of a class declaration and after the parameter list of a member function; places where neither type names nor variable/function names are allowed. This allows them to be contextual keywords. A 'self' keyword would have to appear in expression context, in the place where e.g. 'this' can appear as well. More importantly, a variable named 'self' can appear in this place, and that's why 'self' doesn't work as a contextual keyword.
 
This is a good point. Relaying calls from one mixin to another is a use case I haven't considered so far. I have no good solution for this at the moment.
The alternative CRTP model would allow it without any trouble.

A "rewrite to base classes" semantic model would work for many use cases, but not for the class member access I want. Also, initialization order would get interesting, and dealing with multiple mixins implementing functions from each other or multiple pre-existing base classes would bring lots of complexity in the definition and the explanation of the feature. Motivating example:

struct Foo { virtual void foo() = 0; };
struct Bar { virtual void bar() = 0; };
mixin FooImpl {
  virtual void baz() = 0;
  void foo() { baz(); }
}
mixin BarBazImpl {
  void bar() {}
  void baz() {}
}
struct FooBar : Foo, Bar, mixin FooImpl, mixin BarBazImpl {};

Is the order of the mixins important here? What would the rewritten hierarchy look like?

In the base class model, conflicting names just hide each other; they are not by themselves an error. But going with the model of inheriting conflicting names from multiple bases might be the best model for what I want to achieve after all. 
Sorry, I don't understand. Are you telling inheriting from multiple bases?


Yes. Think about what happens when you inherit from multiple classes that have members with the same name. I think those are the best semantics for mixins with conflicting names too.
 

Vicente J. Botet Escriba

unread,
Jul 19, 2014, 10:12:39 AM7/19/14
to std-pr...@isocpp.org
Le 03/09/13 17:54, corn...@google.com a écrit :

While doing some search about mixins I have found that I didn't replied to this post :(
Hoping this is not too late ;-)


On Monday, September 2, 2013 7:22:37 PM UTC+2, Vicente J. Botet Escriba wrote:
Le 02/09/13 16:51, corn...@google.com a écrit :
Nested templates are simply ugly, and that's without trying to define some of the mixin's methods out-of-line; then you get to multiple template parameter lists, which I bet 90% of C++ programmers have never seen in production code, much less written.
Why would you need to define the mixin's methods out-of-line?

Every other construct in C++ allows out-of-line definition; why should it be impossible for mixins?
I have not said that it is impossible. You said that it was just even uglier.

  

class foo : public mixin X
{
};

This runs into the problems I mentioned about the completeness of foo within the mixin.
I don't see this as a problem, but a future of mixins. A mixin has only sense once instantiated.

I don't understand what you mean by that.
I meant a feature of mixins, not a future.

I want mixins to be able to refer to at least some members of the embedding class from the mixin body, not just the functions.
Me too. We agree here.

 
Have you considered adding a self keyword instead of using this?

For a moment, but I don't see the point. 'self' is completely impossible to add, since it is widely used as a variable/function name, and the new use would be in a context where a variable name can appear. If you know any other conveniently short and logical words that aren't already in wide use in expression context, I'd love to hear about them, though.
The keyword can be contextual.

No, it can't be. That's what I've been trying to say with "would be in a context where a variable name can appear". Contextual keywords only work if the new use for the keyword is in a context where no existing identifier could appear. For example, the 'final' and 'override' contextual keywords only appear after the class name of a class declaration and after the parameter list of a member function; places where neither type names nor variable/function names are allowed. This allows them to be contextual keywords. A 'self' keyword would have to appear in expression context, in the place where e.g. 'this' can appear as well. More importantly, a variable named 'self' can appear in this place, and that's why 'self' doesn't work as a contextual keyword.
You are right it can not be contextual.

On the Flat approach mixins can make use only of members visible from the embedding class.

On the Stack approach mixins can make use either of something under the stack and we use

  this->base_type.member

or something on top of the stack, visible from the embedding class and we use

  self().member





 
This is a good point. Relaying calls from one mixin to another is a use case I haven't considered so far. I have no good solution for this at the moment.
The alternative CRTP model would allow it without any trouble.

A "rewrite to base classes" semantic model would work for many use cases, but not for the class member access I want. Also, initialization order would get interesting, and dealing with multiple mixins implementing functions from each other or multiple pre-existing base classes would bring lots of complexity in the definition and the explanation of the feature.
I agree that your base class model is simpler and easier to understand, but less powerfully as the contribution of each mixin is exclusive, and you can not support each mixing participating on a chain of responsibility, as e.g. the trace() function I showed before.

Motivating example:

struct Foo { virtual void foo() = 0; };
struct Bar { virtual void bar() = 0; };
mixin FooImpl {
  virtual void baz() = 0;
  void foo() { baz(); }
}
mixin BarBazImpl {
  void bar() {}
  void baz() {}
}
struct FooBar : Foo, Bar, mixin FooImpl, mixin BarBazImpl {};

Is the order of the mixins important here? What would the rewritten hierarchy look like?
The mixins can have multiple base classes. let me use __multiple<__pub<X>, __pric<Y> to mean a mixin class inherits publicly from X and privately from Y.
The CRTP model would something like

struct FooBar :  BarBazImpl<FooBar, FooImpl<FooBar, __multiple< __pub<Foo>, __pub<Bar>>>> {};

or

struct FooBar :  mixins< __multiple< __pub<Foo>, __pub<Bar>>,  FooImpl, BarBazImpl> {};

The main problem with this approach is the construction of the mixins using direct C++. But I could hope that a compiler could do the expected behavior, that is construct Foo, the Bar, then FooImpl and last BarBazImpl.



In the base class model, conflicting names just hide each other; they are not by themselves an error. But going with the model of inheriting conflicting names from multiple bases might be the best model for what I want to achieve after all. 
Sorry, I don't understand. Are you telling inheriting from multiple bases?


Yes. Think about what happens when you inherit from multiple classes that have members with the same name. I think those are the best semantics for mixins with conflicting names too.
 

I could agree the conflict arise for non-private data members, but it should not arise for private ones and functions members.

Note again that I'm not against a mixin feature, but IMHO the flat model could be improved with a stack of mixins.

I could be for any syntaxes if what is behind is a stack of mixins, either

struct FooBar : Foo, Bar, mixin FooImpl, mixin BarBazImpl {};

or

struct FooBar : Foo, Bar {
  using mixin FooImpl;
  using mixin BarBazImpl;
};


Best,
Vicente

Vicente J. Botet Escriba

unread,
Jul 22, 2014, 1:37:54 AM7/22/14
to std-pr...@isocpp.org
Le 28/08/13 01:43, Sebastian Redl a écrit :


On Wednesday, August 28, 2013 12:50:14 AM UTC+2, Klaim - Joël Lamotte wrote:

 
3. 

Now if mixins have accessors inside, there seem to be several ways possibilities:

You have pretty much enumerated the access possibilities given the current access specifiers. But my worry goes beyond just access and concerns visibility:

template <typename T>
mixin Foo {
  using my_secret_helper_type = complicated_metaprogram<T>;
  // how do I keep my_secret_helper_type from colliding with types in embedding classes?
  // I can't open a namespace here, but I don't want to start with prefixes again

mixin:
  using this_can_never_conflict = other_metaprogram<T>;
  // awesome, I can use these without worries, because they're truly local to this class
}

I see these options to solve this problem:
1) Do nothing. Have the users use prefixes. This seems extremely inelegant to me.
1a) Merge what can be merged, but otherwise error out, as I described in my original post. Marginally better than 1).
2) Have declarations in the embedding class shadow those in mixins. Except for overloads maybe? But what if two mixins conflict? Earlier shadows later? Later shadows earlier? Declarations co-exist but are ambiguous when accessed?
2a) Embedding class shadows mixins, functions don't overload, multiple mixins coexist and are ambiguous in access. This is the "let's pretend we're still mixing in CRTP base classes" model. But given that I want the model to be "these are put into the class", that's very unintuitive.
3) Provide mixin: or an equivalent way of allowing mixins to hide their implementation details, and have other conflicting parts generate an error. Sounds reasonable, except that, as I said, this would mean that mixins provide a feature that C++ doesn't otherwise have, and I'm worried that they'll be used for that feature alone, leading to obfuscated code. But maybe I shouldn't be worried about that. I can still worry about implementability, though.
3a) Combine 3) with the merging from 1a) for non-hidden things. I like this merging - it feels intuitive and right. But maybe that's just because of where I'm coming from.



I think that mixins should follows the same rules as if they were derived classes. In addition, I believe that mixins are syntactic sugar of the CRTP idiom and that its semantics should be defined as a transformation. I can post it if there is an interest in this approach.

Next follow the rules I find more convenient.

* Declarations on the embedding class/mixin shadows those in the used mixins.

mixin A { void f(); }
class C {
public:
  using mixin A;
  void f()  // shadows A::f()
  {
    //  ...
  }
};

The class C has access to the shadowed members using the mixin name

class C {
public:
  using mixin A;
  void f()  // shadows A::f()
  {
    A::f(); // but the shadowed member can be accessed qualified
    // do more ...
  }
};


* The using mixin directive make visible only the symbols that are not ambiguous and not shadowed. There is no precedence between mixins.

mixin A { void f(); void g(); }
mixin B { void f(); void h();}
class C {
public:
  using mixin A;
  using mixin B;
  // f is ambiguous, g and h are visible
  void x() 
  {
    // this->f(); // error f is ambiguous
    this->g();
    this->h();
    //  ...
  }
};

In order to resolve conflicts, the embedding class/mixin has access to the mixin members using the mixin name and can shadow the conflicting members.

class C {
public:
  using mixin A;
  using mixin B;
  void f() 
  {
    this->A::f();
    this->B::f();
    //  ...
  }
};

Mixins can also use others mixins, so that a stack of mixins can be constructed and the mixin can be template parameters

template <mixin M>
mixin X {
  using mixin M;
  void trace() {
    this->M::trace();
    // ...
  }
};

mixin A { void trace();...}

class C {
  using mixin T = X<A>; // use of alias to simplify the use of the mixin
  void trace() {
    this->T::trace();
    // ...
  }
};

* Mixins names can also be part of the class interface,  

mixin A { void f(); void g(); }
mixin B { void f(); void h();}
class C {
private:
  using mixin A;
public:
  using mixin B;
  void f() 
  {
    this->A::f();
    this->B::f();
    //  ...
  }
};

C c;
c.f(); // OK
c.g(); // ERROR
c.h(); // OK
c.A::f(); // ERROR
c.A::g(); // ERROR
c.B::f(); // OK
c.B::h(); // OK


Vicente

Roland Bock

unread,
Jul 24, 2014, 6:10:16 AM7/24/14
to std-pr...@isocpp.org
--
Thanks for writing this down. I wanted to write pretty much the same for a few weeks now and never got to it :-)

Questions:
  • Would data members be supported as well?
  • Would a mixin be able to access the class that it is used by (similar to CRTP where the base object can access the derived object)?

For the things I have in mind, I would definitely need both items.

Cheers,

Roland


Vicente J. Botet Escriba

unread,
Jul 24, 2014, 2:07:44 PM7/24/14
to std-pr...@isocpp.org
Le 24/07/14 12:10, Roland Bock a écrit :
You are welcome.

Questions:
  • Would data members be supported as well?
Yes. Types would be supported also.


  • Would a mixin be able to access the class that it is used by (similar to CRTP where the base object can access the derived object)?
Yes. This is at least my intent. A mixin has access to all the parts of its embedding class/mixin. This access rights need to be of course transitive.

For the things I have in mind, I would definitely need both items.


Vicente

Roland Bock

unread,
Jul 24, 2014, 2:32:46 PM7/24/14
to std-pr...@isocpp.org
Do you have an idea for the syntax of accessing the embedding class/mixin yet?


For the things I have in mind, I would definitely need both items.



You wrote earlier that mixin semantics should be defined via a transformation from CRTP. I'd be interested in that transformation. Do you think that transformation could be used for a formal proposal?


Best regards,

Roland

Vicente J. Botet Escriba

unread,
Jul 24, 2014, 6:54:10 PM7/24/14
to std-pr...@isocpp.org
Le 24/07/14 20:32, Roland Bock a écrit :
<>--
Thanks for writing this down. I wanted to write pretty much the same for a few weeks now and never got to it :-)

You are welcome.
Questions:
  • Would data members be supported as well?
Yes. Types would be supported also.

  • Would a mixin be able to access the class that it is used by (similar to CRTP where the base object can access the derived object)?
Yes. This is at least my intent. A mixin has access to all the parts of its embedding class/mixin. This access rights need to be of course transitive.
Do you have an idea for the syntax of accessing the embedding class/mixin yet?
We could use final to make it explicit

  this->final::member





For the things I have in mind, I would definitely need both items.


You wrote earlier that mixin semantics should be defined via a transformation from CRTP. I'd be interested in that transformation. Do you think that transformation could be used for a formal proposal?
I don't know if this is a good or bad idea. I know that the mixin model I have in mind  can be transformed to a CRTP implementation. The CRTP implementation can give us the rules we want to emerge and make it possible to prototype it.

Vicente

Roland Bock

unread,
Jul 25, 2014, 5:40:09 AM7/25/14
to std-pr...@isocpp.org
I consider it a good idea. I'd be happy with mixins being a more convenient way of expressing things you can do with CRTP with the benefit, that there is no inheritance involved.

Regards,

Roland

Roland Bock

unread,
Sep 4, 2014, 5:49:01 PM9/4/14
to std-pr...@isocpp.org
On Tuesday, August 27, 2013 11:14:41 PM UTC+2, Sebastian Redl wrote:
The ability to inject additional code into a class is something that I have repeatedly missed. Aside from a number of minor uses, I've twice found myself writing a library that would really have benefited from such a feature.


FYI, I just got confirmation for an open session at CppCon for this topic:

http://sched.co/1qh7PQa (Monday evening)

I believe to have found a way which is both easier and more powerful than what I have seen in this thread. I may be wrong, of course. Looking forward to the discussion. Results will be posted :-)

Cheers,

Roland

renn...@gmail.com

unread,
Feb 1, 2015, 3:06:10 PM2/1/15
to std-pr...@isocpp.org
In the context of extensive usage of unique_pointer and cloneing instead of Sharing, a easy way for "Polymorphic Cloning" would be a great help

mobiphil

unread,
Feb 1, 2015, 5:31:08 PM2/1/15
to std-pr...@isocpp.org
without pretending to having had time to read all the examples, I have the feeling that this is more or less a direction what I called in my previous post "generalized templates"

mixin members {
  void function1();
  int member ;
};

one should just design the correct syntax for this mixins (probably as the body of a template);

class C {

    pasteMixin<something>;
};
//class C will have everything that is 

void globalFunction() {

   trace(pasteMembers<C>);

}

(please also read my prev. post)

regards




Reply all
Reply to author
Forward
0 new messages