Topic: Proposal: Mixins for C++
Author: Sebastian Redl <wasti.redl@gmx.net>
Date: Tue, 27 Aug 2013 14:14:41 -0700 (PDT)
Raw View
------=_Part_1830_14579440.1377638081371
Content-Type: text/plain; charset=ISO-8859-1
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
--
---
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1830_14579440.1377638081371
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">The ability to inject additional code into a class is some=
thing that I have repeatedly missed. Aside from a number of minor uses, I'v=
e twice found myself writing a library that would really have benefited fro=
m such a feature.<br><br>Since someone mentioned this feature a few days ba=
ck, I thought I'd write up my thoughts on the matter and post them here to =
gauge interest and gather comments. Preliminary proposal below.<br><br><br>=
=3D=3D=3D Mixins (Class Extension Blocks) for C++ =3D=3D=3D<br><br>--- Purp=
ose ---<br>Create a solution for injecting repetitive code into classes tha=
t has intuitive<br>syntax, doesn't use the preprocessor, and lacks the draw=
backs of the CRTP.<br><br>--- Background ---<br>There's often a need for cl=
asses to contain somewhat repetitive code. For the<br>purpose of this docum=
ent, we'll go with three motivating examples, in<br>increasing complexity.<=
br><br>Example 1: Non-Copyable<br>Although obsoleted by deleted functions, =
in C++03 this pattern was used to make<br>a class non-copyable:<br><br><spa=
n style=3D"font-family: courier new,monospace;">class foo {<br>private:<br>=
foo(const foo&); // never implemented<br> foo& operato=
r =3D(const foo&); // never implemented<br>};<br></span><br>This repeti=
tive code was hidden in two ways: with macros or with a<br>special-purpose =
base class like boost::noncopyable:<br><br><span style=3D"font-family: cour=
ier new,monospace;">class foo {<br> NONCOPYABLE(foo);<br>};<br><br>cl=
ass foo : boost::noncopyable {<br>};<br></span><br>The macro expands to the=
declaration of the two special members above, and in<br>some cases include=
s the access specifier. It has the following disadvantages:<br>- Uses the p=
reprocessor.<br>- Repeats the class name.<br>- Changes the access specifier=
.. OR Must be placed in private section.<br><br>The base class contains priv=
ate copy functions itself, which prevents the<br>compiler from generating d=
efinitions of these for the derived class. It has<br>the following disadvan=
tages:<br>- Introduces a (usually private) base class. When there is a natu=
ral base class<br> already, this means it introduces multiple inherit=
ance, which is forbidden in<br> some code bases and can even change c=
ode generation (e.g. function pointers in<br> the Microsoft ABI).<br>=
- It could be argued that this is a misuse of base classes.<br><br>Example =
2: Repetitive Operators (Boost.Operators, Boost.Iterator)<br>If I want to d=
efine my own smart pointer, here's what I have to do:<br><span style=3D"fon=
t-family: courier new,monospace;">template <typename T><br>class my_p=
tr {<br> // Custom storage logic.<br> T* raw;<br>public:<br>&nb=
sp; // Custom construction and destruction logic.<br><br> T* get() co=
nst {<br> // Custom access logic.<br> r=
eturn raw;<br> }<br><br> // All these can be defined in terms o=
f get():<br> T& operator *() const { return *get(); }<br> T=
* operator ->() const { return get(); }<br> // This was worse in C=
++03, when the safe-bool idiom had to be used.<br> explicit operator =
bool() const { return get() !=3D nullptr; }<br> bool operator !() con=
st { return get() =3D=3D nullptr; }<br>};<br></span><br>Again, one could de=
fine a macro to encapsulate these operations, or a base<br>class. However, =
the base class solution has the problem that it needs to access<br>the get(=
) function in the derived class. There are two possible ways to deal<br>wit=
h this.<br><br>The first way is to make get() a virtual function in the bas=
e class:<br><span style=3D"font-family: courier new,monospace;">template &l=
t;typename T><br>class smart_ptr_base {<br>public:<br> virtual T* =
get() const =3D 0;<br><br> // Operators as above.<br>};<br>template &=
lt;typename T><br>class my_ptr final : public smart_ptr_base<T> {<=
br> T* get() const override { return raw; }<br>};<br></span><br>The d=
rawbacks of this solution are:<br>- Introduces a public (or the operators a=
re inaccessible) base class that could<br> be misused as an interface=
feature.<br>- Adds a vtable to the class - a 100% size overhead for most s=
mart pointers.<br>- Adds a virtual call to every operation - a massive perf=
ormance overhead<br> compared to the tiny (probably inlined) function=
s we have otherwise. Make the<br> smart pointer class final, and the =
compiler might be smart enough to inline<br> the operators and de-vir=
tualize the get() call.<br><br>The second way is to use the Curiously Recur=
ring Template Pattern:<br><span style=3D"font-family: courier new,monospace=
;">template <typename Derived, typename T><br>class smart_ptr_base {<=
br> const Derived& self() const { return *static_case<const De=
rived*>(this); }<br>public:<br> T& operator *() const { return=
*self().get(); }<br> // etc.<br>};<br>template <typename T><br=
>class my_ptr : public smart_ptr_base<my_ptr<T>, T> {<br> =
T* get() const { return raw; }<br>};<br></span><br>The drawbacks of this s=
olution are:<br>- The CRTP introduces its own boilerplate (the self() funct=
ion).<br>- The CRTP's workings are unintuitive to those introduced to it - =
there's a<br> reason it's called "curiously" recurring. In particular=
, the fact that<br> Derived is an incomplete type in the body of the =
CRTP class is a common<br> stumbling block, and the reason T must be =
passed along in the above example<br> instead of determined by examin=
ing Derived (e.g. to look at a nested typedef).<br> Function type ded=
uction in C++14 can help in some cases, but not all.<br>- The class name mu=
st be repeated, including all its template arguments - the<br> inject=
ed-class-name is not yet visible in the base specification.<br>- The interf=
ace that the CRTP base uses from the derived class must either be<br> =
public, or there must be some friendship between the classes. Specifying t=
he<br> entire base class in a friend declaration can be annoying, and=
friending a<br> type alias wasn't possible before C++11, which led t=
o workarounds such as<br> iterator_core_access (from Boost.Iterator).=
<br><br>Example 3: Polymorphic Cloning<br>When you want to make a copy of a=
n object that you only know by a reference or<br>pointer to the base class,=
the copy constructor is not sufficient, because it<br>is not polymorphic. =
In such cases, the class hierarchy usually provides a clone<br>function. Ho=
wever, implementing this function in every class is another case of<br>boil=
erplate that we want to get rid of.<br><br><span style=3D"font-family: cour=
ier new,monospace;">class base {<br>public:<br> virtual base* clone()=
const =3D 0;<br>};<br><br>class foo : public base {<br>public:<br> v=
irtual foo* clone() const { return new foo(*this); }<br>};<br></span><br>Ag=
ain, a macro is a popular solution, but requires the class name to be<br>re=
peated. A base class with a virtual function is not a solution in this case=
,<br>since it does not actually reduce the amount of boilerplate.<br><br>A =
CRTP base class can be used; however, not in the usual fashion:<br><span st=
yle=3D"font-family: courier new,monospace;">template <typename Derived&g=
t;<br>class cloneable {<br> // self()<br>public:<br> Derived* c=
lone() const { return new Derived(self()); }<br>};<br>class foo : public ba=
se, cloneable<foo> {};<br></span><br>This does not work, because the =
clone() in cloneable does not override the<br>clone() in base. To make it w=
ork, a wrapper would have to be addded to foo that<br>is no shorter than di=
rectly implementing the function.<br><br>Instead, the CRTP class must be in=
jected between base and foo, by templating it<br>on the base class:<br><spa=
n style=3D"font-family: courier new,monospace;">template <typename Base,=
typename Derived><br>class cloneable : public Base {<br> // self(=
)<br>public:<br> using Base::Base;<br> Derived* clone() const {=
return new Derived(self()); }<br>};<br>class foo : public cloneable<bas=
e, foo> {};<br></span><br>The drawbacks of this solution are:<br>- It ob=
fuscates the inheritance hierarchy.<br>- Applying multiple such bases gets =
confusing fast, as they have to be nested.<br>- Before inherited constructo=
rs, correctly forwarding constructors was not<br> practical.<br><br>-=
-- Proposed Solution ---<br>Introduce a new code construct, the "mixin". A =
mixin is similar to a class, but<br>is not a type by itself. Instead, a mix=
in is embedded in (mixed into) a class;<br>its members become members of th=
e class. A mixin is implicitly templated on the<br>type that embeds it, but=
can in addition have further template parameters. A<br>mixin is embedded i=
n a class with a "using mixin" directive.<br><br>Example 1: Non-Copyable<br=
>Here's a non-copyable mixin:<br><br><span style=3D"font-family: courier ne=
w,monospace;">mixin noncopyable {<br> noncopyable(const noncopyable&a=
mp;) =3D delete;<br> noncopyable& operator =3D(const noncopyable&=
amp;) =3D delete;<br>}<br>class foo {<br> using mixin noncopyable;<br=
>};<br></span><br>Here, the compiler will fail to generate the copy functio=
ns for foo, because<br>they would have to call the mixin's copy functions, =
which are deleted. The mixin<br>acts like a data member here, including the=
order of construction (i.e. when<br>data members and mixins are mixed, the=
constructors are called in the order of<br>declaration).<br><br>Example 2:=
Repetitive Operators<br>Here's the smart_ptr mixin:<br><br><span style=3D"=
font-family: courier new,monospace;">mixin smart_ptr {<br>public:<br> =
// Could use decltype(auto) in C++14, but in some cases we can't, e.g. whe=
n<br> // we want to use SFINAE tricks on some overloads.<br> au=
to operator *() const -> decltype(*this->get()) { return *this->ge=
t(); }<br> auto operator ->() const -> decltype(this->get())=
{ return this->get(); }<br> explicit operator bool() const { retu=
rn this->get() !=3D nullptr; }<br> bool operator !() const { retur=
n this->get() =3D=3D nullptr; }<br>}<br>template <typename T><br>c=
lass my_ptr {<br>public:<br> T* get() const { return raw; }<br> =
using mixin smart_ptr;<br>};<br></span><br>To make this work, we need rule=
s about the access to the embedding class from<br>the mixin.<br>Since the m=
ixin is a template, the type of its 'this' pointer is dependent.<br>The syn=
tax for acessing members is the same as that for access to members of<br>de=
pendent base classes: use 'this->' to make the expression dependent and =
delay<br>lookup until instantiation time.<br>When the mixin is instantiated=
, the completeness of the embedding class is<br>treated exactly as if the m=
ixin's code was directly embedded into the class,<br>i.e. members prior to =
the mixin directive are visible, those after are not, and<br>all the usual =
rules for ambiguity and changing meanings apply.<br>Mixins can contain acce=
ss declarations. Their members have the more restricted<br>access of the on=
e they have in the mixin and the one the mixin directive is<br>under. (POD:=
Just ignore the latter?)<br>Mixins can access all members of the embedding=
class, even private ones.<br><br>Example 3: Polymorphic Cloning<br>Here's =
the cloneable mixin:<br><br><span style=3D"font-family: courier new,monospa=
ce;">mixin cloneable {<br>public:<br> decltype(mixin)* clone() const =
override { return new decltype(mixin)(*this); }<br>}<br>class foo : public =
base {<br>public:<br> using mixin cloneable;<br>};<br></span><br>Func=
tions in the mixin override functions the embedding class inherited.<br>The=
'decltype(mixin)' construct names the embedding class. This is to save on<=
br>new keywords.<br><br>More rules:<br>Mixins can have additional template =
parameters, by declaring them using the<br>usual template syntax, e.g. the =
smart_ptr mixin could be done like this too:<br><br><span style=3D"font-fam=
ily: courier new,monospace;">template <typename T><br>mixin smart_ptr=
{<br> T& operator *() const { return *this->get(); }<br> =
; // etc.<br>}<br>template <typename T><br>class my_ptr {<br> /=
/ as usual<br> using mixin smart_ptr<T>;<br>};<br></span><br>Mi=
xin templates can also be specialized on the additional arguments. It is no=
t<br>possible to specialize on the embedding type.<br><br>Members of the mi=
xin become visible in the embedding class at the point of the<br>mixin dire=
ctive. If the mixin is a dependent template instantiation, as in the<br>exa=
mple above, non-dependent lookup cannot find them.<br><br>Mixins can contai=
n every kind of declaration that classes can, including inner<br>types, dat=
a members, and more mixin directives. Mixins cannot have base classes.<br>(=
POD: Should they be able to? The bases could be appended to the list of bas=
es<br>of the embedding class. What kind of problems could that cause?)<br><=
br>--- Additional Use Cases ---<br><br>Building Classes from Blocks:<br>Ima=
gine you're writing a project_iterator: a wrapper around any iterator that<=
br>calls a projection function when being dereferenced.<br><br>Here's what =
this class could look like (some parts omitted):<br><br><span style=3D"font=
-family: courier new,monospace;">template <typename Inner, typename Proj=
ection><br>class project_iterator {<br> Inner inner;<br> Pro=
jection projection;<br> using inner_traits =3D std::iterator_traits&l=
t;Inner>;<br>public:<br> using reference =3D decltype(std::declval=
<Projection>()(<br> &n=
bsp;  =
; *std::declval<Inner>()));<br> using value_type =
=3D typename std::decay<reference>::type;<br> using iterator_ca=
tegory =3D typename std::conditional<<br> =
std::is_lvalue_reference<reference>::value,<br> &nbs=
p; typename inner_traits::iterator_category,<br> &nb=
sp; std::input_iterator_tag<br> >::type;<br>&nbs=
p; // etc.<br><br> // input/output/forward iterator<br> referen=
ce operator *() const { return projection(*inner); }<br> project_iter=
ator& operator ++() { ++inner; return *this; }<br> project_iterat=
or operator ++(int) { auto t =3D *this; ++*this; return t; }<br><br> =
// bidirectional iterator<br> project_iterator& operator --() { -=
-inner; return *this; }<br> project_iterator operator --(int) { auto =
t =3D *this; --*this; return t; }<br><br> // random-access iterator<b=
r> project_iterator& operator +=3D(difference_type d) { inner +=
=3D d; return *this; }<br> project_iterator& operator -=3D(differ=
ence_type d) { inner -=3D d; return *this; }<br> difference_type oper=
ator -(const project_iterator& o) const {<br> return =
inner - o.inner;<br> }<br> reference operator [](difference_typ=
e n) const{ return projection(inner[n]); }<br>};<br></span><br>On first sig=
ht, this looks good. But it comes with a few problems:<br><br>- Even when i=
nstantiated with a forward iterator, the operations of stronger<br> i=
terators are there. SFINAE cannot be used to detect their absence. When the=
<br> user accidentally uses them, he gets template instantiation erro=
rs instead of<br> simple lookup failures.<br> SFINAE cannot be =
used to hide the members, because SFINAE only works with<br> template=
functions.<br>- For an output iterator, difference_type may be void. In su=
ch a case, the<br> signatures taking difference_type as an argument w=
ould be invalid and the<br> instantiation of the class would unexpect=
edly fail. (Note: this is not really<br> relevant in this particular =
example, because a pure output iterator probably<br> doesn't allow a =
function to be applied to its dereference result. However, in<br> sim=
ilar situations, this could be a serious problem.)<br> Nasty typedef =
tricks can be used to work around the instantiation failures,<br> e.g=
.. test the inner difference_type for void and use some random type as a<br>=
fallback. However, complexity rises quickly as such tricks are attem=
pted, both<br> for the implementer and the user of the iterator.<br><=
br>This situation is most easily demonstrated with iterators, but it appear=
s in<br>every scenario where a wrapper around an object that could model an=
y concept<br>from a hierarchy is defined. It can apply to a range library o=
r an I/O library.<br><br>To get completely rid of the methods that don't ap=
ply requires a tag dispatch to<br>building blcoks for the final class. Curr=
ently, this has to be done with base<br>classes and looks something like th=
is:<br><br><span style=3D"font-family: courier new,monospace;">namespace de=
tail {<br> template <typename Inner, typename Projection, typename=
Tag><br> class project_iterator_impl;<br><br> // Base case,=
supported by everything.<br> template <typename Inner, typename P=
rojection><br> class project_iterator_impl<Inner, Projection, i=
nput_iterator_tag> {<br> using inner_traits =3D std::i=
terator_traits<Inner>;<br> protected: // so the other parts can=
access this too<br> Inner inner;<br> P=
rojection projection;<br> // ctors here<br><br> pub=
lic:<br> using reference =3D decltype(std::declval<Pro=
jection>()(<br> &nb=
sp; =
*std::declval<Inner>()));<br> us=
ing value_type =3D typename std::decay<reference>::type;<br><br> =
; reference operator *() const { return projection(*inner); }<b=
r> project_iterator& operator ++() { ++inner; return =
*this; }<br> project_iterator operator ++(int) { auto t =
=3D *this; ++*this; return t; }<br> };<br><br> template <typ=
ename Inner, typename Projection><br> class project_iterator_impl&=
lt;Inner, Projection, forward_iterator_tag><br> &=
nbsp; : public project_iterator_impl<Inner, Projection, input_iterator_t=
ag> {<br> protected:<br> // pull up constructors=
<br> using project_iterator_impl<Inner, Projection, in=
put_iterator_tag><br> ::projec=
t_iterator_impl;<br> };<br><br> template <typename Inner, ty=
pename Projection><br> class project_iterator_impl<Inner, Proje=
ction, bidirectional_iterator_tag><br> : p=
ublic project_iterator_impl<Inner, Projection, forward_iterator_tag> =
{<br> protected:<br> // pull up constructors<br>&nb=
sp; using project_iterator_impl<Inner, Projection, forward_i=
terator_tag><br> ::project_ite=
rator_impl;<br><br> public:<br> project_iterator&am=
p; operator --() { --this->inner; return *this; }<br> =
project_iterator operator --(int) { auto t =3D *this; --*this; return t; }<=
br> };<br><br> // etc for random_access_iterator<br>}<br>templa=
te <typename Inner, typename Projection><br>class project_iterator : =
public project_iterator_impl<Inner, Projection,<br> ty=
pename std::conditional<<br> s=
td::is_lvalue_reference<<br> &n=
bsp; decltype(std::declval<Projection>()(<br> =
&nb=
sp; *std::declval<Inner>()))<br> &=
nbsp; >::value,<br>  =
; typename inner_traits::iterator_category,<br> &nbs=
p; std::input_iterator_tag<br> &nb=
sp; >::type<br> > {<br>public:<br> using iter=
ator_category =3D typename std::conditional<<br> =
std::is_lvalue_reference<decltype(std::declval<Projection>(=
)(<br> &nb=
sp; =
*std::declval&=
lt;Inner>()))>::value,<br> typename inn=
er_traits::iterator_category,<br> std::input_=
iterator_tag<br> >::type;<br>private:<br> using =
base =3D project_iterator_impl<Inner, Projection, iterator_category>;=
<br>public:<br> using base::base;<br>};<br></span><br>With mixins, th=
e building block game could be massively simplified.<br><br><span style=3D"=
font-family: courier new,monospace;">namespace detail {<br> template =
<bool> mixin project_iterator_bidirectional {}<br> template <=
;><br> mixin project_iterator_bidirectional<true> {<br> =
; public:<br> decltype(mixin)& operator --() { --this=
->inner; return *this; }<br> decltype(mixin) operator =
--(int) { auto t =3D *this; --*this; return t; }<br> }<br><br> =
template <bool> mixin project_iterator_random_access {}<br> tem=
plate <><br> mixin project_iterator_random_access<true> {=
<br> using self =3D decltype(mixin);<br><br> public=
:<br> using difference_type =3D typename self::difference=
_type;<br> using reference =3D typename self::reference;<=
br><br> self& operator +=3D(difference_type d) { this=
->inner +=3D d; return *this; }<br> self& operator=
-=3D(difference_type d) { this->inner -=3D d; return *this; }<br> =
difference_type operator -(const self& o) const {<br> =
; return this->inner - o.inner;<br> &=
nbsp; }<br> reference operator [](difference_type n) cons=
t {<br> return this->projection(this->i=
nner[n]);<br> }<br> }<br>}<br><br>template <type=
name Inner, typename Projection><br>class project_iterator {<br> /=
/ base case implemented here - doing it this way in the base class model<br=
> // is possible using CRTP, but only as long as the constructors of =
the pieces<br> // don't need the final version already initialized<br=
><br> using inner_traits =3D std::iterator_traits<Inner>;<br>&n=
bsp; Inner inner;<br> Projection projection;<br><br>public:<br> =
// ctors here<br><br> using reference =3D decltype(std::declval<P=
rojection>()(<br> &=
nbsp; &nbs=
p; *std::declval<Inner>()));<br> using value_type =3D typ=
ename std::decay<reference>::type;<br> using iterator_category =
=3D typename std::conditional<<br> std::is=
_lvalue_reference<reference>::value,<br>  =
; typename inner_traits::iterator_category,<br> &nbs=
p; std::input_iterator_tag<br> >::type;<br><br> =
reference operator *() const { return projection(*inner); }<br> proje=
ct_iterator& operator ++() { ++inner; return *this; }<br> project=
_iterator operator ++(int) { auto t =3D *this; ++*this; return t; }<br><br>=
using mixin detail::project_iterator_bidirectional<<br> &nbs=
p; std::is_base_of<std::bidirectional_iterator_tag, it=
erator_category>::value<br> >;<br> =
; using mixin detail::project_iterator_random_access<<br> &nb=
sp; std::is_base_of<std::random_access_iterator_tag, iterato=
r_category>::value<br> >;<br>};<br></sp=
an><br>On a side note, name conflicts can arise between the embedding class=
and mixins,<br>especially for nested types defined for utility, e.g. diffe=
rence_type and<br>reference in the example above are defined in both the em=
bedding class, and<br>the random access mixin. I believe that the best reso=
lution rules are:<br>- Conflicting variables are an error, with the excepti=
on of static constants<br> with known values, which get merged if the=
values are the same.<br>- Functions overload. If they cannot overload, it'=
s an error.<br>- Types are merged if they are the same type.<br><br>In addi=
tion, it might be useful to make it possible for mixins to have sections<br=
>that are not made visible to the embedding class (e.g. a "mixin:" access<b=
r>specifier), although I am hesitant to really do this, because I can see a=
<br>pattern developing where the entire class body is always put in a mixin=
, and a<br>mixin: specifier is used to create "truly hidden" private sectio=
ns.<br><br>We can add extra syntax for such building blocks along the lines=
of<br>ConceptsLite:<br><br><span style=3D"font-family: courier new,monospa=
ce;">namespace detail {<br> // no template<br> mixin project_it=
erator_bidirectional {<br> // as before<br> }<br>}<=
br><br>template <typename Inner, typename Projection><br>class projec=
t_iterator {<br>public:<br> ...<br> using mixin det=
ail::project_iterator_bidirectional<br> =
requires(std::is_base_of<...>::value);<br>};<br></span><br>Subsume P=
artial Classes:<br>Microsoft added partial classes to C++/CX, where a class=
can have multiple<br>bodies that get merged together. Their primary use ca=
se for this is the ability<br>to generate code from XAML files and have it =
be part of the user class without<br>having to intrude on that class. And i=
f Herb Sutter has his way, they will find<br>their way into C++ eventually =
("FWIW, think partial classes should be considered<br>for C++1y as a standa=
rd language feature"[1]).<br>If one is willing to allow a single mixin dire=
ctive in the user class, mixins<br>can neatly take over this use case. They=
support additional construction code,<br>could possibly support adding bas=
e classes, and should be easy to understand for<br>tools like IntelliSense.=
(These are the three arguments Herb brought up for<br>partial classes over=
a simple #include within the class body in the discussion<br>linked above.=
)<br><br>[1] http://channel9.msdn.com/Shows/C9-GoingNative/GoingNative-3-Th=
e-CCX-Episode-with-Marian-Luparu#c634565677496092669<br><br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1830_14579440.1377638081371--
.
Author: =?UTF-8?Q?Klaim_=2D_Jo=C3=ABl_Lamotte?= <mjklaim@gmail.com>
Date: Wed, 28 Aug 2013 00:52:28 +0200
Raw View
--089e0111bcfa35d23c04e4f5ba86
Content-Type: text/plain; charset=ISO-8859-1
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.
--
---
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e0111bcfa35d23c04e4f5ba86
Content-Type: text/html; charset=ISO-8859-1
<div dir="ltr">One last thing:<br>without accessors, I believe mixin implementations would be a bit difficult<br>if it needs to add member objects and need to keep them private.<br><br><br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/</a>.<br />
--089e0111bcfa35d23c04e4f5ba86--
.
Author: =?UTF-8?Q?Klaim_=2D_Jo=C3=ABl_Lamotte?= <mjklaim@gmail.com>
Date: Wed, 28 Aug 2013 00:50:14 +0200
Raw View
--047d7b3a975c2f5b8604e4f5b27b
Content-Type: text/plain; charset=ISO-8859-1
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
--
---
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--047d7b3a975c2f5b8604e4f5b27b
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Very interesting feature.<div>I have a lot of recent code =
that would benefit a lot in clarity by using such kind of feature<br>becaus=
e composing a class public interface happen often and there is, as demonstr=
ated here, no easy way to do it in C++.<br>
<br>Questions:<br><br>1. does mixin member function have to be defined befo=
re the "using" call? does all the mixin code have to be in the de=
claration?<br>=A0 =A0 can it be mixins be written with declaration and defi=
nition separate? (the same question but said differently)<br>
<br>2.<br><br><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px=
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left=
-style:solid;padding-left:1ex">Example 3: Polymorphic Cloning<br>Here's=
the cloneable mixin:<br>
mixin cloneable {<br>public:<br>=A0 decltype(mixin)* clone() const override=
{ return new decltype(mixin)(*this); }<br>}<br>class foo : public base {<b=
r>public:<br>=A0 using mixin cloneable;<br>};<br>Functions in the mixin ove=
rride functions the embedding class inherited.<br>
The 'decltype(mixin)' construct names the embedding class. This is =
to save on<br>new keywords.</blockquote><div><br></div><div><br></div><div>=
I don't understand why =A0the return type of clone() is decltype(mixin)=
*. <br>
If this clone() function is overloading base::clone(), then shouldn't i=
t return base*? <br>If yes, then this clonable mixin should be templated wi=
th the base class as parameter.<br>Am I correct?<br><br>3.=A0<br><br><block=
quote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-w=
idth:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding=
-left:1ex">
In addition, it might be useful to make it possible for mixins to have sect=
ions<br>that are not made visible to the embedding class (e.g. a "mixi=
n:" access<br>specifier), although I am hesitant to really do this, be=
cause I can see a<br>
pattern developing where the entire class body is always put in a mixin, an=
d a<br>mixin: specifier is used to create "truly hidden" private =
sections.</blockquote><div><br></div><div>I have no strong opinion but here=
is my thinking on this:<br>
It appear that mixins would be good to compose the public interface of a cl=
ass at least.<br>Now, if it's always "public" and access depe=
nds on access of the using declaration,<br>it means that if someone wants t=
o compose a class with private and public parts,<br>
in which case he can:<br>=A01. make sure there is are mixins that have a co=
rrect interface for public access and another mixins that are used in priva=
te access<br>=A0 =A0 =A0This forces mixin implementor to sometime cut their=
work into several mixins, which look a bit like it would make the code les=
s easy to follow <br>
=A0 =A0 =A0(like when there is too much callback calls);<br>=A02. use mixin=
s only for public parts as expected, use private inheritance or member obje=
ct composition for non-public parts;<br><br>Now if mixins have accessors in=
side, there seem to be several ways possibilities:<br>
=A0A. the mixin accessor is always used, whatever the using call context:<b=
r><br>mixin K {=A0<br>=A0 =A0 =A0private:<br>=A0 =A0 =A0void foo();<br>}<br=
><br>class U<br>{<br>public:<br>=A0 =A0 using mixin K; // foo() is private =
and accessible by U members<br>
};<br><br>B. mixin accessors are only public and private: private code is n=
ot exposed to the mixin user at all<br><br><br>mixin K {=A0<br>=A0 =A0 =A0p=
rivate:<br>=A0 =A0 =A0void foo();</div><div>=A0 =A0 =A0public:<br>=A0 =A0 =
=A0void bar();<br>}<br>
<br>class U<br>{<br>public:<br>=A0 =A0 using mixin K; // foo() is not acces=
sible by U members, bar() is public<br>};<br><br>class V<br>{<br>private:<b=
r>=A0 =A0 using mixin K; // bar() is accessible only by V members, foo() is=
still not accessible at all<br>
};<br><br><br>C. mixin accessors will have the lower access right allowed b=
etween the mixin code and the using code:<br><br><div>mixin K {=A0<br>=A0 =
=A0 =A0private:<br>=A0 =A0 =A0void foo();</div><div>=A0 =A0 =A0protected:</=
div>=A0 =A0 =A0void meow();<div>
=A0 =A0 =A0public:<br>=A0 =A0 =A0void bar();<br>}<br><br>class U<br>{<br>pu=
blic:<br>=A0 =A0 using mixin K;<br>=A0 =A0 /* foo() is public<br>=A0 =A0 =
=A0 =A0meow() is protected (accessible by U members and U child classes)<br=
>=A0 =A0 =A0 =A0bar() is private (accessible by U members only)</div>
<div>=A0 =A0 */<br>};<br><br>class V<br>{<br>private:<br>=A0 =A0 using mixi=
n K;=A0</div><div>=A0 =A0 /* foo() is private=A0(accessible by V members on=
ly)<div>=A0 =A0 =A0 =A0meow() is private<br>=A0 =A0 =A0 =A0bar() is private=
</div><div>=A0 =A0 */</div>};<br>
</div><br>class W<br>{<br>protected:<br>=A0 =A0 using mixin K;=A0<div>=A0 =
=A0 /* foo() is protected=A0(accessible by U members and U child classes)<d=
iv>=A0 =A0 =A0 =A0meow() is protected<br>=A0 =A0 =A0 =A0bar() is private</d=
iv><div>=A0 =A0 */</div></div>
};<br><br>D. mixin accessors follow exactly the same accessor logic than cl=
ass inheritance (which is like C but bar() is never accesible):<br><br><br>=
<div>mixin K {=A0<br>=A0 =A0 =A0private:<br>=A0 =A0 =A0void foo();</div><di=
v>=A0 =A0 =A0protected:</div>
=A0 =A0 =A0void meow();<div>=A0 =A0 =A0public:<br>=A0 =A0 =A0void bar();<br=
>}<br><br>class U<br>{<br>public:<br>=A0 =A0 using mixin K;<br>=A0 =A0 /* f=
oo() is public<br>=A0 =A0 =A0 =A0meow() is protected (accessible by U membe=
rs and U child classes)<br>=A0 =A0 =A0 =A0bar() is never accessible</div>
<div>=A0 =A0 */<br>};<br><br>class V<br>{<br>private:<br>=A0 =A0 using mixi=
n K;=A0</div><div>=A0 =A0 /* foo() is private=A0(accessible by V members on=
ly)<div>=A0 =A0 =A0 =A0meow() is protected<br>=A0 =A0 =A0 =A0bar() is never=
accessible</div><div>=A0 =A0 */</div>
};<br></div><br>class W<br>{<br>protected:<br>=A0 =A0 using mixin K;=A0<div=
>=A0 =A0 /* foo() is protected=A0(accessible by U members and U child class=
es)<div>=A0 =A0 =A0 =A0meow() is protected<br>=A0 =A0 =A0 =A0bar() is never=
accessible</div><div>=A0 =A0 */</div>
</div>};<br><br>I guess this needs some thinking.<br><br><br>Joel Lamotte<b=
r><br></div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7b3a975c2f5b8604e4f5b27b--
.
Author: Sebastian Redl <wasti.redl@gmx.net>
Date: Tue, 27 Aug 2013 16:43:45 -0700 (PDT)
Raw View
------=_Part_469_12710195.1377647025746
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On Wednesday, August 28, 2013 12:50:14 AM UTC+2, Klaim - Jo=EBl Lamotte wro=
te:
>
> Very interesting feature.
>
Thank you.
> Questions:
>
> 1. does mixin member function have to be defined before the "using" call?=
=20
> does all the mixin code have to be in the declaration?
> can it be mixins be written with declaration and definition separate?=
=20
> (the same question but said differently)
>
Mixin member implementations can be out of line, and even after a class has=
=20
embedded the mixin, but keep in mind that a mixin is always like a=20
template, The implementations need to be visible to whoever tries to=20
instantiate them (by using them).
=20
>
> 2.
>
> Example 3: Polymorphic Cloning
>> Here's the cloneable mixin:
>> mixin cloneable {
>> public:
>> decltype(mixin)* clone() const override { return new=20
>> 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=20
>> save on
>> new keywords.
>
>
>
> I don't understand why the return type of clone() is decltype(mixin)*.=
=20
> If this clone() function is overloading base::clone(), then shouldn't it=
=20
> return base*?=20
> If yes, then this clonable mixin should be templated with the base class=
=20
> as parameter.
> Am I correct?
>
>
clone() typically has a covariant return type, so that when I call clone()=
=20
on an object statically known to be at least a Derived, I get a Derived*=20
back instead of a Base*. That's why the mixin's clone() returns=20
decltype(mixin)*.
=20
> 3.=20
>
> Now if mixins have accessors inside, there seem to be several ways=20
> possibilities:
>
You have pretty much enumerated the access possibilities given the current=
=20
access specifiers. But my worry goes beyond just access and concerns=20
visibility:
template <typename T>
mixin Foo {
using my_secret_helper_type =3D complicated_metaprogram<T>;
// how do I keep my_secret_helper_type from colliding with types in=20
embedding classes?
// I can't open a namespace here, but I don't want to start with prefixes=
=20
again
mixin:
using this_can_never_conflict =3D other_metaprogram<T>;
// awesome, I can use these without worries, because they're truly local=
=20
to this class
}
I see these options to solve this problem:
1) Do nothing. Have the users use prefixes. This seems extremely inelegant=
=20
to me.
1a) Merge what can be merged, but otherwise error out, as I described in my=
=20
original post. Marginally better than 1).
2) Have declarations in the embedding class shadow those in mixins. Except=
=20
for overloads maybe? But what if two mixins conflict? Earlier shadows=20
later? Later shadows earlier? Declarations co-exist but are ambiguous when=
=20
accessed?
2a) Embedding class shadows mixins, functions don't overload, multiple=20
mixins coexist and are ambiguous in access. This is the "let's pretend=20
we're still mixing in CRTP base classes" model. But given that I want the=
=20
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=20
implementation details, and have other conflicting parts generate an error.=
=20
Sounds reasonable, except that, as I said, this would mean that mixins=20
provide a feature that C++ doesn't otherwise have, and I'm worried that=20
they'll be used for that feature alone, leading to obfuscated code. But=20
maybe I shouldn't be worried about that. I can still worry about=20
implementability, though.
3a) Combine 3) with the merging from 1a) for non-hidden things. I like this=
=20
merging - it feels intuitive and right. But maybe that's just because of=20
where I'm coming from.
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_469_12710195.1377647025746
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Wednesday, August 28, 2013 12:50:14 AM UTC+2, K=
laim - Jo=EBl Lamotte wrote:<blockquote class=3D"gmail_quote" style=3D"marg=
in: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><d=
iv dir=3D"ltr">Very interesting feature.<div></div></div></blockquote><div>=
<br>Thank you.<br><br></div><blockquote class=3D"gmail_quote" style=3D"marg=
in: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><d=
iv dir=3D"ltr"><div><br>Questions:<br><br>1. does mixin member function hav=
e to be defined before the "using" call? does all the mixin code have to be=
in the declaration?<br> can it be mixins be written with decl=
aration and definition separate? (the same question but said differently)<b=
r></div></div></blockquote><div><br>Mixin member implementations can be out=
of line, and even after a class has embedded the mixin, but keep in mind t=
hat a mixin is always like a template, The implementations need to be visib=
le to whoever tries to instantiate them (by using them).<br> </div><bl=
ockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border=
-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>
<br>2.<br><br><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px=
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left=
-style:solid;padding-left:1ex">Example 3: Polymorphic Cloning<br>Here's the=
cloneable mixin:<br>
mixin cloneable {<br>public:<br> decltype(mixin)* clone() const overr=
ide { return new decltype(mixin)(*this); }<br>}<br>class foo : public base =
{<br>public:<br> using mixin cloneable;<br>};<br>Functions in the mix=
in override functions the embedding class inherited.<br>
The 'decltype(mixin)' construct names the embedding class. This is to save =
on<br>new keywords.</blockquote><div><br></div><div><br></div><div>I don't =
understand why the return type of clone() is decltype(mixin)*. <br>
If this clone() function is overloading base::clone(), then shouldn't it re=
turn base*? <br>If yes, then this clonable mixin should be templated with t=
he base class as parameter.<br>Am I correct?<br><br></div></div></div></blo=
ckquote><div><br>clone() typically has a covariant return type, so that whe=
n 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() retu=
rns decltype(mixin)*.<br><br> </div><blockquote class=3D"gmail_quote" =
style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-l=
eft: 1ex;"><div dir=3D"ltr"><div><div>3. <br><br><div>Now if mixins ha=
ve accessors inside, there seem to be several ways possibilities:<br>
</div></div></div></div></blockquote><div><br>You have pretty much enumerat=
ed the access possibilities given the current access specifiers. But my wor=
ry goes beyond just access and concerns visibility:<br><br>template <typ=
ename T><br>mixin Foo {<br> using my_secret_helper_type =3D compli=
cated_metaprogram<T>;<br> // how do I keep my_secret_helper_typ=
e from colliding with types in embedding classes?<br> // I can't open=
a namespace here, but I don't want to start with prefixes again<br><br>mix=
in:<br> using this_can_never_conflict =3D other_metaprogram<T>;=
<br> // awesome, I can use these without worries, because they're tru=
ly local to this class<br>}<br><br>I see these options to solve this proble=
m:<br>1) Do nothing. Have the users use prefixes. This seems extremely inel=
egant to me.<br>1a) Merge what can be merged, but otherwise error out, as I=
described in my original post. Marginally better than 1).<br>2) Have decla=
rations in the embedding class shadow those in mixins. Except for overloads=
maybe? But what if two mixins conflict? Earlier shadows later? Later shado=
ws earlier? Declarations co-exist but are ambiguous when accessed?<br>2a) E=
mbedding class shadows mixins, functions don't overload, multiple mixins co=
exist and are ambiguous in access. This is the "let's pretend we're still m=
ixing in CRTP base classes" model. But given that I want the model to be "t=
hese are put into the class", that's very unintuitive.<br>3) Provide mixin:=
or an equivalent way of allowing mixins to hide their implementation detai=
ls, 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 f=
eature alone, leading to obfuscated code. But maybe I shouldn't be worried =
about that. I can still worry about implementability, though.<br>3a) Combin=
e 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 c=
oming from.<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin:=
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
</blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_469_12710195.1377647025746--
.
Author: =?UTF-8?Q?R=C3=B3bert_D=C3=A1vid?= <lrdxgm@gmail.com>
Date: Tue, 27 Aug 2013 16:59:34 -0700 (PDT)
Raw View
------=_Part_509_8787223.1377647974124
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
2013. augusztus 27., kedd 23:14:41 UTC+2 id=C5=91pontban Sebastian Redl a=
=20
k=C3=B6vetkez=C5=91t =C3=ADrta:
>
> The ability to inject additional code into a class is something that I=20
> have repeatedly missed. Aside from a number of minor uses, I've twice fou=
nd=20
> myself writing a library that would really have benefited from such a=20
> feature.
>
> Since someone mentioned this feature a few days back, I thought I'd write=
=20
> up my thoughts on the matter and post them here to gauge interest and=20
> gather comments. Preliminary proposal below.
>
>
> =3D=3D=3D Mixins (Class Extension Blocks) for C++ =3D=3D=3D
>
> --- Purpose ---
> Create a solution for injecting repetitive code into classes that has=20
> 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=
=20
> 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 t=
o=20
> make
> a class non-copyable:
>
> class foo {
> private:
> foo(const foo&); // never implemented
> foo& operator =3D(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, an=
d=20
> in
> some cases includes the access specifier. It has the following=20
> 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 h=
as
> the following disadvantages:
> - Introduces a (usually private) base class. When there is a natural base=
=20
> class
> already, this means it introduces multiple inheritance, which is=20
> forbidden in
> some code bases and can even change code generation (e.g. function=20
> 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() !=3D nullptr; }
> bool operator !() const { return get() =3D=3D nullptr; }
> };
>
> Again, one could define a macro to encapsulate these operations, or a bas=
e
> class. However, the base class solution has the problem that it needs to=
=20
> access
> the get() function in the derived class. There are two possible ways to=
=20
> 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 =3D 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=
=20
> could
> be misused as an interface feature.
> - Adds a vtable to the class - a 100% size overhead for most smart=20
> pointers.
> - Adds a virtual call to every operation - a massive performance overhead
> compared to the tiny (probably inlined) functions we have otherwise.=20
> Make the
> smart pointer class final, and the compiler might be smart enough to=20
> 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)=
;=20
> }
> 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=20
> example
> instead of determined by examining Derived (e.g. to look at a nested=20
> 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 -=
=20
> the
> injected-class-name is not yet visible in the base specification.
> - The interface that the CRTP base uses from the derived class must eithe=
r=20
> be
> public, or there must be some friendship between the classes. Specifyin=
g=20
> the
> entire base class in a friend declaration can be annoying, and friendin=
g=20
> 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=20
> reference or
> pointer to the base class, the copy constructor is not sufficient, becaus=
e=20
> it
> is not polymorphic. In such cases, the class hierarchy usually provides a=
=20
> clone
> function. However, implementing this function in every class is another=
=20
> case of
> boilerplate that we want to get rid of.
>
> class base {
> public:
> virtual base* clone() const =3D 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=
=20
> 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 th=
e
> clone() in base. To make it work, a wrapper would have to be addded to fo=
o=20
> that
> is no shorter than directly implementing the function.
>
> Instead, the CRTP class must be injected between base and foo, by=20
> 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=20
> nested.
> - Before inherited constructors, correctly forwarding constructors was no=
t
> practical.
>
> --- Proposed Solution ---
> Introduce a new code construct, the "mixin". A mixin is similar to a=20
> class, but
> is not a type by itself. Instead, a mixin is embedded in (mixed into) a=
=20
> class;
> its members become members of the class. A mixin is implicitly templated=
=20
> on the
> type that embeds it, but can in addition have further template parameters=
..=20
> 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&) =3D delete;
> noncopyable& operator =3D(const noncopyable&) =3D delete;
> }
> class foo {
> using mixin noncopyable;
> };
>
> Here, the compiler will fail to generate the copy functions for foo,=20
> because
> they would have to call the mixin's copy functions, which are deleted. Th=
e=20
> mixin
> acts like a data member here, including the order of construction (i.e.=
=20
> when
> data members and mixins are mixed, the constructors are called in the=20
> 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.=
=20
> when
> // we want to use SFINAE tricks on some overloads.
> auto operator *() const -> decltype(*this->get()) { return *this->get()=
;=20
> }
> auto operator ->() const -> decltype(this->get()) { return this->get();=
}
> explicit operator bool() const { return this->get() !=3D nullptr; }
> bool operator !() const { return this->get() =3D=3D 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=
=20
> from
> the mixin.
> Since the mixin is a template, the type of its 'this' pointer is dependen=
t.
> The syntax for acessing members is the same as that for access to members=
=20
> of
> dependent base classes: use 'this->' to make the expression dependent and=
=20
> delay
> lookup until instantiation time.
> When the mixin is instantiated, the completeness of the embedding class i=
s
> treated exactly as if the mixin's code was directly embedded into the=20
> class,
> i.e. members prior to the mixin directive are visible, those after are=20
> not, and
> all the usual rules for ambiguity and changing meanings apply.
> Mixins can contain access declarations. Their members have the more=20
> 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=20
> 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 sav=
e=20
> on
> new keywords.
>
> More rules:
> Mixins can have additional template parameters, by declaring them using t=
he
> usual template syntax, e.g. the smart_ptr mixin could be done like this=
=20
> 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 i=
s=20
> not
> possible to specialize on the embedding type.
>
> Members of the mixin become visible in the embedding class at the point o=
f=20
> the
> mixin directive. If the mixin is a dependent template instantiation, as i=
n=20
> the
> example above, non-dependent lookup cannot find them.
>
> Mixins can contain every kind of declaration that classes can, including=
=20
> inner
> types, data members, and more mixin directives. Mixins cannot have base=
=20
> classes.
> (POD: Should they be able to? The bases could be appended to the list of=
=20
> 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=
=20
> 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 =3D std::iterator_traits<Inner>;
> public:
> using reference =3D decltype(std::declval<Projection>()(
> *std::declval<Inner>()));
> using value_type =3D typename std::decay<reference>::type;
> using iterator_category =3D 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 =3D *this; ++*this; return t=
; }
>
> // bidirectional iterator
> project_iterator& operator --() { --inner; return *this; }
> project_iterator operator --(int) { auto t =3D *this; --*this; return t=
; }
>
> // random-access iterator
> project_iterator& operator +=3D(difference_type d) { inner +=3D d; retu=
rn=20
> *this; }
> project_iterator& operator -=3D(difference_type d) { inner -=3D d; retu=
rn=20
> *this; }
> difference_type operator -(const project_iterator& o) const {
> return inner - o.inner;
> }
> reference operator [](difference_type n) const{ return=20
> 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=20
> stronger
> iterators are there. SFINAE cannot be used to detect their absence. Whe=
n=20
> the
> user accidentally uses them, he gets template instantiation errors=20
> instead of
> simple lookup failures.
> SFINAE cannot be used to hide the members, because SFINAE only works wi=
th
> template functions.
> - For an output iterator, difference_type may be void. In such a case, th=
e
> signatures taking difference_type as an argument would be invalid and t=
he
> instantiation of the class would unexpectedly fail. (Note: this is not=
=20
> really
> relevant in this particular example, because a pure output iterator=20
> probably
> doesn't allow a function to be applied to its dereference result.=20
> However, in
> similar situations, this could be a serious problem.)
> Nasty typedef tricks can be used to work around the instantiation=20
> failures,
> e.g. test the inner difference_type for void and use some random type a=
s=20
> a
> fallback. However, complexity rises quickly as such tricks are=20
> attempted, both
> for the implementer and the user of the iterator.
>
> This situation is most easily demonstrated with iterators, but it appears=
=20
> in
> every scenario where a wrapper around an object that could model any=20
> concept
> from a hierarchy is defined. It can apply to a range library or an I/O=20
> library.
>
> To get completely rid of the methods that don't apply requires a tag=20
> dispatch to
> building blcoks for the final class. Currently, this has to be done with=
=20
> 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 =3D std::iterator_traits<Inner>;
> protected: // so the other parts can access this too
> Inner inner;
> Projection projection;
> // ctors here
>
> public:
> using reference =3D decltype(std::declval<Projection>()(
> *std::declval<Inner>()));
> using value_type =3D typename std::decay<reference>::type;
>
> reference operator *() const { return projection(*inner); }
> project_iterator& operator ++() { ++inner; return *this; }
> project_iterator operator ++(int) { auto t =3D *this; ++*this; return=
t;=20
> }
> };
>
> template <typename Inner, typename Projection>
> class project_iterator_impl<Inner, Projection, forward_iterator_tag>
> : public project_iterator_impl<Inner, Projection,=20
> 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,=20
> bidirectional_iterator_tag>
> : public project_iterator_impl<Inner, Projection,=20
> 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 =3D *this; --*this; return=
t;=20
> }
> };
>
> // 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 =3D 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 =3D project_iterator_impl<Inner, Projection, iterator_catego=
ry>;
> 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 =3D *this; --*this; return =
t; }
> }
>
> template <bool> mixin project_iterator_random_access {}
> template <>
> mixin project_iterator_random_access<true> {
> using self =3D decltype(mixin);
>
> public:
> using difference_type =3D typename self::difference_type;
> using reference =3D typename self::reference;
>
> self& operator +=3D(difference_type d) { this->inner +=3D d; return *=
this;=20
> }
> self& operator -=3D(difference_type d) { this->inner -=3D d; return *=
this;=20
> }
> 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 mod=
el
> // is possible using CRTP, but only as long as the constructors of the=
=20
> pieces
> // don't need the final version already initialized
>
> using inner_traits =3D std::iterator_traits<Inner>;
> Inner inner;
> Projection projection;
>
> public:
> // ctors here
>
> using reference =3D decltype(std::declval<Projection>()(
> *std::declval<Inner>()));
> using value_type =3D typename std::decay<reference>::type;
> using iterator_category =3D 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 =3D *this; ++*this; return t=
; }
>
> using mixin detail::project_iterator_bidirectional<
> std::is_base_of<std::bidirectional_iterator_tag,=20
> iterator_category>::value
> >;
> using mixin detail::project_iterator_random_access<
> std::is_base_of<std::random_access_iterator_tag,=20
> iterator_category>::value
> >;
> };
>
> On a side note, name conflicts can arise between the embedding class and=
=20
> 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, a=
nd
> the random access mixin. I believe that the best resolution rules are:
> - Conflicting variables are an error, with the exception of static=20
> 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=20
> 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,=
=20
> 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 multipl=
e
> bodies that get merged together. Their primary use case for this is the=
=20
> ability
> to generate code from XAML files and have it be part of the user class=20
> without
> having to intrude on that class. And if Herb Sutter has his way, they wil=
l=20
> find
> their way into C++ eventually ("FWIW, think partial classes should be=20
> considered
> for C++1y as a standard language feature"[1]).
> If one is willing to allow a single mixin directive in the user class,=20
> mixins
> can neatly take over this use case. They support additional construction=
=20
> code,
> could possibly support adding base classes, and should be easy to=20
> understand for
> tools like IntelliSense. (These are the three arguments Herb brought up f=
or
> partial classes over a simple #include within the class body in the=20
> discussion
> linked above.)
>
> [1] *
> http://channel9.msdn.com/Shows/C9-GoingNative/GoingNative-3-The-CCX-Episo=
de-with-Marian-Luparu#c634565677496092669
> *<http://channel9.msdn.com/Shows/C9-GoingNative/GoingNative-3-The-CCX-Epi=
sode-with-Marian-Luparu#c634565677496092669>
>
> =20
All your example cases can be solved with a good (private or public) base=
=20
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;=20
N3690 at this time)
class foo {
foo(const foo&) =3D delete;
foo& operator=3D(const foo&) =3D delete;
};
(Side note: let me point out that noncopyable and noncopyassignable are two=
=20
different things, although very frequently used together.)
The only thing is missing (?) is a standard std::noncopyable "mixin": the=
=20
one above, with a correct name. This solution does not use macros, does not=
=20
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"=20
relation. Saying that Foo is-a noncopyable thing isn't worse than Java or=
=20
C# saying everything is-a Object, so I don't believe it is a misuse of base=
=20
classes. I don't really see how an empty base class can screw up code=20
generation, maybe with a bad compiler, but in that case you are probably=20
not even using C++11, or if the multiple inheritance is banned because of=
=20
policy reasons, then you are asking a language extension because you don't=
=20
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=
=20
reason why you don't write the template parameter out while defining the=20
constructors.
- The CRTP's workings are unintuitive to those introduced to it - there's a=
=20
> reason it's called "curiously" recurring. In particular, the fact that=20
> Derived is an incomplete type in the body of the CRTP class is a common=
=20
> stumbling block, and the reason T must be passed along in the above examp=
le=20
> instead of determined by examining Derived (e.g. to look at a nested=20
> typedef). Function type deduction in C++14 can help in some cases, but no=
t=20
> all.
- The class name must be repeated, including all its template arguments -=
=20
> 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=
=20
> be public, or there must be some friendship between the classes. Specifyi=
ng=20
> the entire base class in a friend declaration can be annoying, and=20
> friending a type alias wasn't possible before C++11, which led to=20
> workarounds such as iterator_core_access (from Boost.Iterator).
>
Well, ok, you are right, but are you trying to give private functionality=
=20
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=20
virtual, otherwise you will call the base class' clone from the base=20
pointer/reference. You mention macros as downside again, but even your=20
virtual function example doesn't have any...
So sorry but -1. Mixins are dumbed-down versions of multiple inheritance so=
=20
languages without that can have that functionality, but quite handicapped=
=20
in a few cases. C++/CX is such a language, so it needs mixins, aka partial=
=20
classes. There is absolutely no need for mixins in proper C++, as long as=
=20
you use the language properly. It *does* need a few tweaks here and there,=
=20
but I don't feel mixins are such.
If something is missing, the standard "mixin" classes, starting with=20
std::non_copyable, std::non_movable, and so on. Call for papers is until=20
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!)
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_509_8787223.1377647974124
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">2013. augusztus 27., kedd 23:14:41 UTC+2 id=C5=91pontban S=
ebastian Redl a k=C3=B6vetkez=C5=91t =C3=ADrta:<blockquote class=3D"gmail_q=
uote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-co=
lor: rgb(204, 204, 204); border-left-width: 1px; border-left-style: solid;"=
><div dir=3D"ltr">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=20
myself writing a library that would really have benefited from such a=20
feature.<br><br>Since someone mentioned this feature a few days back, I=20
thought I'd write up my thoughts on the matter and post them here to=20
gauge interest and gather comments. Preliminary proposal below.<br><br><br>=
=3D=3D=3D Mixins (Class Extension Blocks) for C++ =3D=3D=3D<br><br>--- Purp=
ose ---<br>Create a solution for injecting repetitive code into classes tha=
t has intuitive<br>syntax, doesn't use the preprocessor, and lacks the draw=
backs of the CRTP.<br><br>--- Background ---<br>There's often a need for cl=
asses to contain somewhat repetitive code. For the<br>purpose of this docum=
ent, we'll go with three motivating examples, in<br>increasing complexity.<=
br><br>Example 1: Non-Copyable<br>Although obsoleted by deleted functions, =
in C++03 this pattern was used to make<br>a class non-copyable:<br><br><spa=
n style=3D"font-family: courier new,monospace;">class foo {<br>private:<br>=
foo(const foo&); // never implemented<br> foo& operato=
r =3D(const foo&); // never implemented<br>};<br></span><br>This repeti=
tive code was hidden in two ways: with macros or with a<br>special-purpose =
base class like boost::noncopyable:<br><br><span style=3D"font-family: cour=
ier new,monospace;">class foo {<br> NONCOPYABLE(foo);<br>};<br><br>cl=
ass foo : boost::noncopyable {<br>};<br></span><br>The macro expands to the=
declaration of the two special members above, and in<br>some cases include=
s the access specifier. It has the following disadvantages:<br>- Uses the p=
reprocessor.<br>- Repeats the class name.<br>- Changes the access specifier=
.. OR Must be placed in private section.<br><br>The base class contains priv=
ate copy functions itself, which prevents the<br>compiler from generating d=
efinitions of these for the derived class. It has<br>the following disadvan=
tages:<br>- Introduces a (usually private) base class. When there is a natu=
ral base class<br> already, this means it introduces multiple inherit=
ance, which is forbidden in<br> some code bases and can even change c=
ode generation (e.g. function pointers in<br> the Microsoft ABI).<br>=
- It could be argued that this is a misuse of base classes.<br><br>Example =
2: Repetitive Operators (Boost.Operators, Boost.Iterator)<br>If I want to d=
efine my own smart pointer, here's what I have to do:<br><span style=3D"fon=
t-family: courier new,monospace;">template <typename T><br>class my_p=
tr {<br> // Custom storage logic.<br> T* raw;<br>public:<br>&nb=
sp; // Custom construction and destruction logic.<br><br> T* get() co=
nst {<br> // Custom access logic.<br> r=
eturn raw;<br> }<br><br> // All these can be defined in terms o=
f get():<br> T& operator *() const { return *get(); }<br> T=
* operator ->() const { return get(); }<br> // This was worse in C=
++03, when the safe-bool idiom had to be used.<br> explicit operator =
bool() const { return get() !=3D nullptr; }<br> bool operator !() con=
st { return get() =3D=3D nullptr; }<br>};<br></span><br>Again, one could de=
fine a macro to encapsulate these operations, or a base<br>class. However, =
the base class solution has the problem that it needs to access<br>the get(=
) function in the derived class. There are two possible ways to deal<br>wit=
h this.<br><br>The first way is to make get() a virtual function in the bas=
e class:<br><span style=3D"font-family: courier new,monospace;">template &l=
t;typename T><br>class smart_ptr_base {<br>public:<br> virtual T* =
get() const =3D 0;<br><br> // Operators as above.<br>};<br>template &=
lt;typename T><br>class my_ptr final : public smart_ptr_base<T> {<=
br> T* get() const override { return raw; }<br>};<br></span><br>The d=
rawbacks of this solution are:<br>- Introduces a public (or the operators a=
re inaccessible) base class that could<br> be misused as an interface=
feature.<br>- Adds a vtable to the class - a 100% size overhead for most s=
mart pointers.<br>- Adds a virtual call to every operation - a massive perf=
ormance overhead<br> compared to the tiny (probably inlined) function=
s we have otherwise. Make the<br> smart pointer class final, and the =
compiler might be smart enough to inline<br> the operators and de-vir=
tualize the get() call.<br><br>The second way is to use the Curiously Recur=
ring Template Pattern:<br><span style=3D"font-family: courier new,monospace=
;">template <typename Derived, typename T><br>class smart_ptr_base {<=
br> const Derived& self() const { return *static_case<const De=
rived*>(this); }<br>public:<br> T& operator *() const { return=
*self().get(); }<br> // etc.<br>};<br>template <typename T><br=
>class my_ptr : public smart_ptr_base<my_ptr<T>, T> {<br> =
T* get() const { return raw; }<br>};<br></span><br>The drawbacks of this s=
olution are:<br>- The CRTP introduces its own boilerplate (the self() funct=
ion).<br>- The CRTP's workings are unintuitive to those introduced to it - =
there's a<br> reason it's called "curiously" recurring. In particular=
, the fact that<br> Derived is an incomplete type in the body of the =
CRTP class is a common<br> stumbling block, and the reason T must be =
passed along in the above example<br> instead of determined by examin=
ing Derived (e.g. to look at a nested typedef).<br> Function type ded=
uction in C++14 can help in some cases, but not all.<br>- The class name mu=
st be repeated, including all its template arguments - the<br> inject=
ed-class-name is not yet visible in the base specification.<br>- The interf=
ace that the CRTP base uses from the derived class must either be<br> =
public, or there must be some friendship between the classes. Specifying t=
he<br> entire base class in a friend declaration can be annoying, and=
friending a<br> type alias wasn't possible before C++11, which led t=
o workarounds such as<br> iterator_core_access (from Boost.Iterator).=
<br><br>Example 3: Polymorphic Cloning<br>When you want to make a copy of a=
n object that you only know by a reference or<br>pointer to the base class,=
the copy constructor is not sufficient, because it<br>is not polymorphic. =
In such cases, the class hierarchy usually provides a clone<br>function. Ho=
wever, implementing this function in every class is another case of<br>boil=
erplate that we want to get rid of.<br><br><span style=3D"font-family: cour=
ier new,monospace;">class base {<br>public:<br> virtual base* clone()=
const =3D 0;<br>};<br><br>class foo : public base {<br>public:<br> v=
irtual foo* clone() const { return new foo(*this); }<br>};<br></span><br>Ag=
ain, a macro is a popular solution, but requires the class name to be<br>re=
peated. A base class with a virtual function is not a solution in this case=
,<br>since it does not actually reduce the amount of boilerplate.<br><br>A =
CRTP base class can be used; however, not in the usual fashion:<br><span st=
yle=3D"font-family: courier new,monospace;">template <typename Derived&g=
t;<br>class cloneable {<br> // self()<br>public:<br> Derived* c=
lone() const { return new Derived(self()); }<br>};<br>class foo : public ba=
se, cloneable<foo> {};<br></span><br>This does not work, because the =
clone() in cloneable does not override the<br>clone() in base. To make it w=
ork, a wrapper would have to be addded to foo that<br>is no shorter than di=
rectly implementing the function.<br><br>Instead, the CRTP class must be in=
jected between base and foo, by templating it<br>on the base class:<br><spa=
n style=3D"font-family: courier new,monospace;">template <typename Base,=
typename Derived><br>class cloneable : public Base {<br> // self(=
)<br>public:<br> using Base::Base;<br> Derived* clone() const {=
return new Derived(self()); }<br>};<br>class foo : public cloneable<bas=
e, foo> {};<br></span><br>The drawbacks of this solution are:<br>- It ob=
fuscates the inheritance hierarchy.<br>- Applying multiple such bases gets =
confusing fast, as they have to be nested.<br>- Before inherited constructo=
rs, correctly forwarding constructors was not<br> practical.<br><br>-=
-- Proposed Solution ---<br>Introduce a new code construct, the "mixin". A =
mixin is similar to a class, but<br>is not a type by itself. Instead, a mix=
in is embedded in (mixed into) a class;<br>its members become members of th=
e class. A mixin is implicitly templated on the<br>type that embeds it, but=
can in addition have further template parameters. A<br>mixin is embedded i=
n a class with a "using mixin" directive.<br><br>Example 1: Non-Copyable<br=
>Here's a non-copyable mixin:<br><br><span style=3D"font-family: courier ne=
w,monospace;">mixin noncopyable {<br> noncopyable(const noncopyable&a=
mp;) =3D delete;<br> noncopyable& operator =3D(const noncopyable&=
amp;) =3D delete;<br>}<br>class foo {<br> using mixin noncopyable;<br=
>};<br></span><br>Here, the compiler will fail to generate the copy functio=
ns for foo, because<br>they would have to call the mixin's copy functions, =
which are deleted. The mixin<br>acts like a data member here, including the=
order of construction (i.e. when<br>data members and mixins are mixed, the=
constructors are called in the order of<br>declaration).<br><br>Example 2:=
Repetitive Operators<br>Here's the smart_ptr mixin:<br><br><span style=3D"=
font-family: courier new,monospace;">mixin smart_ptr {<br>public:<br> =
// Could use decltype(auto) in C++14, but in some cases we can't, e.g. whe=
n<br> // we want to use SFINAE tricks on some overloads.<br> au=
to operator *() const -> decltype(*this->get()) { return *this->ge=
t(); }<br> auto operator ->() const -> decltype(this->get())=
{ return this->get(); }<br> explicit operator bool() const { retu=
rn this->get() !=3D nullptr; }<br> bool operator !() const { retur=
n this->get() =3D=3D nullptr; }<br>}<br>template <typename T><br>c=
lass my_ptr {<br>public:<br> T* get() const { return raw; }<br> =
using mixin smart_ptr;<br>};<br></span><br>To make this work, we need rule=
s about the access to the embedding class from<br>the mixin.<br>Since the m=
ixin is a template, the type of its 'this' pointer is dependent.<br>The syn=
tax for acessing members is the same as that for access to members of<br>de=
pendent base classes: use 'this->' to make the expression dependent and =
delay<br>lookup until instantiation time.<br>When the mixin is instantiated=
, the completeness of the embedding class is<br>treated exactly as if the m=
ixin's code was directly embedded into the class,<br>i.e. members prior to =
the mixin directive are visible, those after are not, and<br>all the usual =
rules for ambiguity and changing meanings apply.<br>Mixins can contain acce=
ss declarations. Their members have the more restricted<br>access of the on=
e they have in the mixin and the one the mixin directive is<br>under. (POD:=
Just ignore the latter?)<br>Mixins can access all members of the embedding=
class, even private ones.<br><br>Example 3: Polymorphic Cloning<br>Here's =
the cloneable mixin:<br><br><span style=3D"font-family: courier new,monospa=
ce;">mixin cloneable {<br>public:<br> decltype(mixin)* clone() const =
override { return new decltype(mixin)(*this); }<br>}<br>class foo : public =
base {<br>public:<br> using mixin cloneable;<br>};<br></span><br>Func=
tions in the mixin override functions the embedding class inherited.<br>The=
'decltype(mixin)' construct names the embedding class. This is to save on<=
br>new keywords.<br><br>More rules:<br>Mixins can have additional template =
parameters, by declaring them using the<br>usual template syntax, e.g. the =
smart_ptr mixin could be done like this too:<br><br><span style=3D"font-fam=
ily: courier new,monospace;">template <typename T><br>mixin smart_ptr=
{<br> T& operator *() const { return *this->get(); }<br> =
; // etc.<br>}<br>template <typename T><br>class my_ptr {<br> /=
/ as usual<br> using mixin smart_ptr<T>;<br>};<br></span><br>Mi=
xin templates can also be specialized on the additional arguments. It is no=
t<br>possible to specialize on the embedding type.<br><br>Members of the mi=
xin become visible in the embedding class at the point of the<br>mixin dire=
ctive. If the mixin is a dependent template instantiation, as in the<br>exa=
mple above, non-dependent lookup cannot find them.<br><br>Mixins can contai=
n every kind of declaration that classes can, including inner<br>types, dat=
a members, and more mixin directives. Mixins cannot have base classes.<br>(=
POD: Should they be able to? The bases could be appended to the list of bas=
es<br>of the embedding class. What kind of problems could that cause?)<br><=
br>--- Additional Use Cases ---<br><br>Building Classes from Blocks:<br>Ima=
gine you're writing a project_iterator: a wrapper around any iterator that<=
br>calls a projection function when being dereferenced.<br><br>Here's what =
this class could look like (some parts omitted):<br><br><span style=3D"font=
-family: courier new,monospace;">template <typename Inner, typename Proj=
ection><br>class project_iterator {<br> Inner inner;<br> Pro=
jection projection;<br> using inner_traits =3D std::iterator_traits&l=
t;Inner>;<br>public:<br> using reference =3D decltype(std::declval=
<<wbr>Projection>()(<br> &nb=
sp; =
*std::declval<Inner>()));<br> using value_ty=
pe =3D typename std::decay<reference>::type;<br> using iterator=
_category =3D typename std::conditional<<br> &nbs=
p; std::is_lvalue_reference<<wbr>reference>::value,<br> &n=
bsp; typename inner_traits::iterator_<wbr>category,<br> &n=
bsp; std::input_iterator_tag<br> >::=
type;<br> // etc.<br><br> // input/output/forward iterator<br>&=
nbsp; reference operator *() const { return projection(*inner); }<br> =
project_iterator& operator ++() { ++inner; return *this; }<br> p=
roject_iterator operator ++(int) { auto t =3D *this; ++*this; return t; }<b=
r><br> // bidirectional iterator<br> project_iterator& oper=
ator --() { --inner; return *this; }<br> project_iterator operator --=
(int) { auto t =3D *this; --*this; return t; }<br><br> // random-acce=
ss iterator<br> project_iterator& operator +=3D(difference_type d=
) { inner +=3D d; return *this; }<br> project_iterator& operator =
-=3D(difference_type d) { inner -=3D d; return *this; }<br> differenc=
e_type operator -(const project_iterator& o) const {<br> &nb=
sp; return inner - o.inner;<br> }<br> reference operator [](dif=
ference_type n) const{ return projection(inner[n]); }<br>};<br></span><br>O=
n first sight, this looks good. But it comes with a few problems:<br><br>- =
Even when instantiated with a forward iterator, the operations of stronger<=
br> iterators are there. SFINAE cannot be used to detect their absenc=
e. When the<br> user accidentally uses them, he gets template instant=
iation errors instead of<br> simple lookup failures.<br> SFINAE=
cannot be used to hide the members, because SFINAE only works with<br>&nbs=
p; template functions.<br>- For an output iterator, difference_type may be =
void. In such a case, the<br> signatures taking difference_type as an=
argument would be invalid and the<br> instantiation of the class wou=
ld unexpectedly fail. (Note: this is not really<br> relevant in this =
particular example, because a pure output iterator probably<br> doesn=
't allow a function to be applied to its dereference result. However, in<br=
> similar situations, this could be a serious problem.)<br> Nas=
ty typedef tricks can be used to work around the instantiation failures,<br=
> e.g. test the inner difference_type for void and use some random ty=
pe as a<br> fallback. However, complexity rises quickly as such trick=
s are attempted, both<br> for the implementer and the user of the ite=
rator.<br><br>This situation is most easily demonstrated with iterators, bu=
t it appears in<br>every scenario where a wrapper around an object that cou=
ld model any concept<br>from a hierarchy is defined. It can apply to a rang=
e library or an I/O library.<br><br>To get completely rid of the methods th=
at don't apply requires a tag dispatch to<br>building blcoks for the final =
class. Currently, this has to be done with base<br>classes and looks someth=
ing like this:<br><br><span style=3D"font-family: courier new,monospace;">n=
amespace detail {<br> template <typename Inner, typename Projectio=
n, typename Tag><br> class project_iterator_impl;<br><br> //=
Base case, supported by everything.<br> template <typename Inner,=
typename Projection><br> class project_iterator_impl<Inner, Pr=
ojection, input_iterator_tag> {<br> using inner_traits=
=3D std::iterator_traits<Inner>;<br> protected: // so the othe=
r parts can access this too<br> Inner inner;<br> &nb=
sp; Projection projection;<br> // ctors here<br><br=
> public:<br> using reference =3D decltype(std::dec=
lval<<wbr>Projection>()(<br>  =
; &n=
bsp; *std::declval<Inner>()));<br> =
; using value_type =3D typename std::decay<reference>::ty=
pe;<br><br> reference operator *() const { return project=
ion(*inner); }<br> project_iterator& operator ++() { =
++inner; return *this; }<br> project_iterator operator ++=
(int) { auto t =3D *this; ++*this; return t; }<br> };<br><br> t=
emplate <typename Inner, typename Projection><br> class project=
_iterator_impl<Inner, Projection, forward_iterator_tag><br> &nbs=
p; : public project_iterator_impl<Inner, Projection, i=
nput_iterator_tag> {<br> protected:<br> // pull =
up constructors<br> using project_iterator_impl<Inner,=
Projection, input_iterator_tag><br> =
::project_iterator_impl;<br> };<br><br> template <typ=
ename Inner, typename Projection><br> class project_iterator_impl&=
lt;Inner, Projection, bidirectional_iterator_tag><br> &=
nbsp; : public project_iterator_impl<Inner, Projection, forward_it=
erator_tag> {<br> protected:<br> // pull up cons=
tructors<br> using project_iterator_impl<Inner, Projec=
tion, forward_iterator_tag><br>  =
; ::project_iterator_impl;<br><br> public:<br> proj=
ect_iterator& operator --() { --this->inner; return *this; }<br>&nbs=
p; project_iterator operator --(int) { auto t =3D *this; --*thi=
s; return t; }<br> };<br><br> // etc for random_access_iterator=
<br>}<br>template <typename Inner, typename Projection><br>class proj=
ect_iterator : public project_iterator_impl<Inner, Projection,<br> =
typename std::conditional<<br>  =
; std::is_lvalue_reference<<br>  =
; decltype(std::declval<<wbr>Project=
ion>()(<br> &=
nbsp; *std::declval<Inner>()))<br>  =
; >::value,<br> &nb=
sp; typename inner_traits::iterator_<wbr>category,<=
br> std::input_iterator_tag<br>&n=
bsp; >::type<br> > {<br>pub=
lic:<br> using iterator_category =3D typename std::conditional<<br=
> std::is_lvalue_reference<<wbr>decltype(s=
td::declval<<wbr>Projection>()(<br> &nbs=
p; &=
nbsp; <wbr=
> *std::declval<Inner>()))>::<wbr>value,<b=
r> typename inner_traits::iterator_<wbr>categ=
ory,<br> std::input_iterator_tag<br> &nb=
sp; >::type;<br>private:<br> using base =3D project_iterator=
_impl<Inner, Projection, iterator_category>;<br>public:<br> usi=
ng base::base;<br>};<br></span><br>With mixins, the building block game cou=
ld be massively simplified.<br><br><span style=3D"font-family: courier new,=
monospace;">namespace detail {<br> template <bool> mixin projec=
t_iterator_bidirectional {}<br> template <><br> mixin pro=
ject_iterator_<wbr>bidirectional<true> {<br> public:<br> &=
nbsp; decltype(mixin)& operator --() { --this->inner; return *=
this; }<br> decltype(mixin) operator --(int) { auto t =3D=
*this; --*this; return t; }<br> }<br><br> template <bool>=
; mixin project_iterator_random_access {}<br> template <><br>&n=
bsp; mixin project_iterator_random_<wbr>access<true> {<br>  =
; using self =3D decltype(mixin);<br><br> public:<br> &nbs=
p; using difference_type =3D typename self::difference_type;<br> =
; using reference =3D typename self::reference;<br><br> &n=
bsp; self& operator +=3D(difference_type d) { this->inner +=3D=
d; return *this; }<br> self& operator -=3D(differenc=
e_type d) { this->inner -=3D d; return *this; }<br> di=
fference_type operator -(const self& o) const {<br> &n=
bsp; return this->inner - o.inner;<br> }<br>&nbs=
p; reference operator [](difference_type n) const {<br> &n=
bsp; return this->projection(this->inner[<wbr>n]);<=
br> }<br> }<br>}<br><br>template <typename Inner=
, typename Projection><br>class project_iterator {<br> // base cas=
e implemented here - doing it this way in the base class model<br> //=
is possible using CRTP, but only as long as the constructors of the pieces=
<br> // don't need the final version already initialized<br><br> =
; using inner_traits =3D std::iterator_traits<Inner>;<br> Inner=
inner;<br> Projection projection;<br><br>public:<br> // ctors =
here<br><br> using reference =3D decltype(std::declval<<wbr>Projec=
tion>()(<br> =
&nb=
sp; *std::declval<Inner>()));<br> using value_type =3D typename=
std::decay<reference>::type;<br> using iterator_category =3D t=
ypename std::conditional<<br> std::is_lval=
ue_reference<<wbr>reference>::value,<br>  =
; typename inner_traits::iterator_<wbr>category,<br>  =
; std::input_iterator_tag<br> >::type;<br><br>&n=
bsp; reference operator *() const { return projection(*inner); }<br> =
project_iterator& operator ++() { ++inner; return *this; }<br> pr=
oject_iterator operator ++(int) { auto t =3D *this; ++*this; return t; }<br=
><br> using mixin detail::project_iterator_<wbr>bidirectional<<br>=
std::is_base_of<std::<wbr>bidirectional_i=
terator_tag, iterator_category>::value<br> =
>;<br> using mixin detail::project_iterator_<wbr>random_access<=
;<br> std::is_base_of<std::random_<wbr>acc=
ess_iterator_tag, iterator_category>::value<br> &=
nbsp; >;<br>};<br></span><br>On a side note, name conflicts can arise be=
tween the embedding class and mixins,<br>especially for nested types define=
d for utility, e.g. difference_type and<br>reference in the example above a=
re defined in both the embedding class, and<br>the random access mixin. I b=
elieve that the best resolution rules are:<br>- Conflicting variables are a=
n error, with the exception of static constants<br> with known values=
, which get merged if the values are the same.<br>- Functions overload. If =
they cannot overload, it's an error.<br>- Types are merged if they are the =
same type.<br><br>In addition, it might be useful to make it possible for m=
ixins to have sections<br>that are not made visible to the embedding class =
(e.g. a "mixin:" access<br>specifier), although I am hesitant to really do =
this, because I can see a<br>pattern developing where the entire class body=
is always put in a mixin, and a<br>mixin: specifier is used to create "tru=
ly hidden" private sections.<br><br>We can add extra syntax for such buildi=
ng blocks along the lines of<br>ConceptsLite:<br><br><span style=3D"font-fa=
mily: courier new,monospace;">namespace detail {<br> // no template<b=
r> mixin project_iterator_bidirectional {<br> // as=
before<br> }<br>}<br><br>template <typename Inner, typename Proje=
ction><br>class project_iterator {<br>public:<br> ...<br>&nb=
sp; using mixin detail::project_iterator_<wbr>bidirectional<br> =
requires(std::is_base_of<...>:<wbr>:va=
lue);<br>};<br></span><br>Subsume Partial Classes:<br>Microsoft added parti=
al classes to C++/CX, where a class can have multiple<br>bodies that get me=
rged together. Their primary use case for this is the ability<br>to generat=
e code from XAML files and have it be part of the user class without<br>hav=
ing to intrude on that class. And if Herb Sutter has his way, they will fin=
d<br>their way into C++ eventually ("FWIW, think partial classes should be =
considered<br>for C++1y as a standard language feature"[1]).<br>If one is w=
illing to allow a single mixin directive in the user class, mixins<br>can n=
eatly take over this use case. They support additional construction code,<b=
r>could possibly support adding base classes, and should be easy to underst=
and for<br>tools like IntelliSense. (These are the three arguments Herb bro=
ught up for<br>partial classes over a simple #include within the class body=
in the discussion<br>linked above.)<br><br>[1] <a href=3D"http://channel9.=
msdn.com/Shows/C9-GoingNative/GoingNative-3-The-CCX-Episode-with-Marian-Lup=
aru#c634565677496092669" target=3D"_blank"><u><font color=3D"#0066cc">http:=
//channel9.msdn.com/<wbr>Shows/C9-GoingNative/<wbr>GoingNative-3-The-CCX-Ep=
isode-<wbr>with-Marian-Luparu#<wbr>c634565677496092669</font></u></a><br><b=
r></div></blockquote><div> <br>All your example cases can be solved wi=
th a good (private or public) base class, I try to show you how:<br><br><bl=
ockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-=
left: 1ex; border-left-color: rgb(204, 204, 204); border-left-width: 1px; b=
order-left-style: solid;"><div>Example 1: Non-Copyable<br></div></blockquot=
e>It would be better if you start from C++11 (or even the current draft; N3=
690 at this time)<br><div class=3D"prettyprint" style=3D"border: 1px solid =
rgb(187, 187, 187); word-wrap: break-word; background-color: rgb(250, 250, =
250);"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span clas=
s=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);">class</span><span=
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> foo </span><s=
pan class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">{</span=
><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"><br>&nbs=
p; foo</span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 10=
2, 0);">(</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0=
, 136);">const</span><span class=3D"styled-by-prettify" style=3D"color: rgb=
(0, 0, 0);"> foo</span><span class=3D"styled-by-prettify" style=3D"color: r=
gb(102, 102, 0);">&)</span><span class=3D"styled-by-prettify" style=3D"=
color: rgb(0, 0, 0);"> </span><span class=3D"styled-by-prettify" style=3D"c=
olor: rgb(102, 102, 0);">=3D</span><span class=3D"styled-by-prettify" style=
=3D"color: rgb(0, 0, 0);"> </span><span class=3D"styled-by-prettify" style=
=3D"color: rgb(0, 0, 136);">delete</span><span class=3D"styled-by-prettify"=
style=3D"color: rgb(102, 102, 0);">;</span><span class=3D"styled-by-pretti=
fy" style=3D"color: rgb(0, 0, 0);"><br> foo</span><span class=3D"styl=
ed-by-prettify" style=3D"color: rgb(102, 102, 0);">&</span><span class=
=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> </span><span class=
=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);">operator</span><sp=
an class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">=3D(</sp=
an><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);">cons=
t</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> =
foo</span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, =
0);">&)</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0,=
0, 0);"> </span><span class=3D"styled-by-prettify" style=3D"color: rgb(102=
, 102, 0);">=3D</span><span class=3D"styled-by-prettify" style=3D"color: rg=
b(0, 0, 0);"> </span><span class=3D"styled-by-prettify" style=3D"color: rgb=
(0, 0, 136);">delete</span><span class=3D"styled-by-prettify" style=3D"colo=
r: rgb(102, 102, 0);">;</span><span class=3D"styled-by-prettify" style=3D"c=
olor: rgb(0, 0, 0);"><br></span><span class=3D"styled-by-prettify" style=3D=
"color: rgb(102, 102, 0);">};</span><span class=3D"styled-by-prettify" styl=
e=3D"color: rgb(0, 0, 0);"><br></span></div></code></div>(Side
note: let me point out that noncopyable and noncopyassignable are two=20
different things, although very frequently used together.)<br>The only=20
thing is missing (?) is a standard std::noncopyable "mixin": the one=20
above, with a correct name. This solution does not use macros, does not=20
repeat the class name, and does not change the access classifier=20
anywhere.<br>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=20
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=20
screw up code generation, maybe with a bad compiler, but in that case=20
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=20
extension because you don't use the whole language..<br><span style=3D"font=
-family: courier new,monospace;"></span><br><blockquote class=3D"gmail_quot=
e" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color=
: rgb(204, 204, 204); border-left-width: 1px; border-left-style: solid;">Ex=
ample 2: Repetitive Operators (Boost.Operators, Boost.Iterator)<br></blockq=
uote><div><br>You can do CRTP a lot better:<br></div><div class=3D"prettypr=
int" style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-word; =
background-color: rgb(250, 250, 250);"><code class=3D"prettyprint"><div cla=
ss=3D"subprettyprint"><span class=3D"styled-by-prettify" style=3D"color: rg=
b(0, 0, 136);">template</span><span class=3D"styled-by-prettify" style=3D"c=
olor: rgb(0, 0, 0);"> </span><span class=3D"styled-by-prettify" style=3D"co=
lor: rgb(102, 102, 0);"><</span><span class=3D"styled-by-prettify" style=
=3D"color: rgb(0, 0, 136);">typename</span><span class=3D"styled-by-prettif=
y" style=3D"color: rgb(0, 0, 0);"> </span><span class=3D"styled-by-prettify=
" style=3D"color: rgb(102, 0, 102);">Derived</span><span class=3D"styled-by=
-prettify" style=3D"color: rgb(102, 102, 0);">></span><span class=3D"sty=
led-by-prettify" style=3D"color: rgb(0, 0, 0);"><br></span><span class=3D"s=
tyled-by-prettify" style=3D"color: rgb(0, 0, 136);">class</span><span class=
=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> smart_ptr_base </sp=
an><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">{<=
/span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"><br=
> </span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,=
136);">const</span><span class=3D"styled-by-prettify" style=3D"color: rgb(=
0, 0, 0);"> </span><span class=3D"styled-by-prettify" style=3D"color: rgb(1=
02, 0, 102);">Derived</span><span class=3D"styled-by-prettify" style=3D"col=
or: rgb(102, 102, 0);">&</span><span class=3D"styled-by-prettify" style=
=3D"color: rgb(0, 0, 0);"> </span><span class=3D"styled-by-prettify" style=
=3D"color: rgb(0, 0, 136);">self</span><span class=3D"styled-by-prettify" s=
tyle=3D"color: rgb(102, 102, 0);">()</span><span class=3D"styled-by-prettif=
y" style=3D"color: rgb(0, 0, 0);"> </span><span class=3D"styled-by-prettify=
" style=3D"color: rgb(0, 0, 136);">const</span><span class=3D"styled-by-pre=
ttify" style=3D"color: rgb(0, 0, 0);"> </span><span class=3D"styled-by-pret=
tify" style=3D"color: rgb(102, 102, 0);">{</span><span class=3D"styled-by-p=
rettify" style=3D"color: rgb(0, 0, 0);"> </span><span class=3D"styled-by-pr=
ettify" style=3D"color: rgb(0, 0, 136);">return</span><span class=3D"styled=
-by-prettify" style=3D"color: rgb(0, 0, 0);"> </span><span class=3D"styled-=
by-prettify" style=3D"color: rgb(102, 102, 0);">*</span><span class=3D"styl=
ed-by-prettify" style=3D"color: rgb(0, 0, 0);">static_cast</span><span clas=
s=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);"><</span><spa=
n class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);">const</span=
><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> </span>=
<span class=3D"styled-by-prettify" style=3D"color: rgb(102, 0, 102);">Deriv=
ed</span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0=
);">*>(</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, =
0, 136);">this</span><span class=3D"styled-by-prettify" style=3D"color: rgb=
(102, 102, 0);">);</span><span class=3D"styled-by-prettify" style=3D"color:=
rgb(0, 0, 0);"> </span><span class=3D"styled-by-prettify" style=3D"color: =
rgb(102, 102, 0);">}</span><span class=3D"styled-by-prettify" style=3D"colo=
r: rgb(0, 0, 0);"><br></span><span class=3D"styled-by-prettify" style=3D"co=
lor: rgb(0, 0, 136);"><code class=3D"prettyprint"><span class=3D"styled-by-=
prettify" style=3D"color: rgb(0, 0, 0);"> </span><span class=3D"style=
d-by-prettify" style=3D"color: rgb(0, 0, 136);">typedef</span><span class=
=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> </span><span class=
=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);">decltype</span><sp=
an class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">(self.</=
span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);">ge=
t</span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0)=
;">())</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0=
);"> T;<br></span><span class=3D"styled-by-prettify" style=3D"color: rgb(0,=
0, 0);"></span></code>public</span><span class=3D"styled-by-prettify" styl=
e=3D"color: rgb(102, 102, 0);">:</span><span class=3D"styled-by-prettify" s=
tyle=3D"color: rgb(0, 0, 0);"><br> T</span><span class=3D"styled-by-p=
rettify" style=3D"color: rgb(102, 102, 0);">&</span><span class=3D"styl=
ed-by-prettify" style=3D"color: rgb(0, 0, 0);"> </span><span class=3D"style=
d-by-prettify" style=3D"color: rgb(0, 0, 136);">operator</span><span class=
=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> </span><span class=
=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">*()</span><span =
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> </span><span c=
lass=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);">const</span><s=
pan class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> </span><sp=
an class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">{</span>=
<span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> </span><=
span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);">return</=
span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> </s=
pan><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">*=
</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);">=
self</span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,=
0);">().</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0=
, 136);">get</span><span class=3D"styled-by-prettify" style=3D"color: rgb(1=
02, 102, 0);">();</span><span class=3D"styled-by-prettify" style=3D"color: =
rgb(0, 0, 0);"> </span><span class=3D"styled-by-prettify" style=3D"color: r=
gb(102, 102, 0);">}</span><span class=3D"styled-by-prettify" style=3D"color=
: rgb(0, 0, 0);"><br> </span><span class=3D"styled-by-prettify" style=
=3D"color: rgb(136, 0, 0);">// etc.</span><span class=3D"styled-by-prettify=
" style=3D"color: rgb(0, 0, 0);"><br></span><span class=3D"styled-by-pretti=
fy" style=3D"color: rgb(102, 102, 0);">};</span><span class=3D"styled-by-pr=
ettify" style=3D"color: rgb(0, 0, 0);"><br></span><span class=3D"styled-by-=
prettify" style=3D"color: rgb(0, 0, 136);">template</span><span class=3D"st=
yled-by-prettify" style=3D"color: rgb(0, 0, 0);"> </span><span class=3D"sty=
led-by-prettify" style=3D"color: rgb(102, 102, 0);"><</span><span class=
=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);">typename</span><sp=
an class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> T</span><sp=
an class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">></sp=
an><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"><br></=
span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);">cl=
ass</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
> my_ptr </span><span class=3D"styled-by-prettify" style=3D"color: rgb(102,=
102, 0);">:</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0=
, 0, 0);"> </span><span class=3D"styled-by-prettify" style=3D"color: rgb(0,=
0, 136);">public</span><span class=3D"styled-by-prettify" style=3D"color: =
rgb(0, 0, 0);"> smart_ptr_base</span><span class=3D"styled-by-prettify" sty=
le=3D"color: rgb(102, 102, 0);"><</span><span class=3D"styled-by-prettif=
y" style=3D"color: rgb(0, 0, 0);">my_ptr</span><span class=3D"styled-by-pre=
ttify" style=3D"color: rgb(0, 0, 0);"></span><span class=3D"styled-by-prett=
ify" style=3D"color: rgb(102, 102, 0);">></span><span class=3D"styled-by=
-prettify" style=3D"color: rgb(0, 0, 0);"> </span><span class=3D"styled-by-=
prettify" style=3D"color: rgb(102, 102, 0);">{</span><span class=3D"styled-=
by-prettify" style=3D"color: rgb(0, 0, 0);"><br> T</span><span class=
=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">*</span><span cl=
ass=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> </span><span cla=
ss=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);">get</span><span =
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">()</span><s=
pan class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> </span><sp=
an class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);">const</spa=
n><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> </span=
><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">{</s=
pan><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> </sp=
an><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);">retu=
rn</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);">=
raw</span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,=
0);">;</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, =
0);"> </span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 10=
2, 0);">}</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0=
, 0);"><br></span><span class=3D"styled-by-prettify" style=3D"color: rgb(10=
2, 102, 0);">};</span><span class=3D"styled-by-prettify" style=3D"color: rg=
b(0, 0, 0);"><br></span></div></code></div>Works
in VS2012 already.. Note: there is no need to write my_ptr<T>,=20
same reason why you don't write the template parameter out while=20
defining the constructors.<br><br><blockquote class=3D"gmail_quote" style=
=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(20=
4, 204, 204); border-left-width: 1px; border-left-style: solid;">-
The CRTP's workings are unintuitive to those introduced to it - there's
a reason it's called "curiously" recurring. In particular, the fact=20
that Derived is an incomplete type in the body of the CRTP class is a=20
common stumbling block, and the reason T must be passed along in the=20
above example instead of determined by examining Derived (e.g. to look=20
at a nested typedef). Function type deduction in C++14 can help in some=20
cases, but not all.</blockquote><blockquote class=3D"gmail_quote" style=3D"=
margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 2=
04, 204); border-left-width: 1px; border-left-style: solid;">-
The class name must be repeated, including all its template arguments -
the injected-class-name is not yet visible in the base specification.<br><=
/blockquote>None of this is true, see above example.<br><br><blockquote cla=
ss=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; b=
order-left-color: rgb(204, 204, 204); border-left-width: 1px; border-left-s=
tyle: solid;">-
The interface that the CRTP base uses from the derived class must=20
either be public, or there must be some friendship between the classes.=20
Specifying the entire base class in a friend declaration can be=20
annoying, and friending a type alias wasn't possible before C++11, which
led to workarounds such as iterator_core_access (from Boost.Iterator).<br>=
</blockquote>Well,
ok, you are right, but are you trying to give private functionality=20
through a mixin? I fail to see where can that be useful.<br><br><blockquote=
class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1e=
x; border-left-color: rgb(204, 204, 204); border-left-width: 1px; border-le=
ft-style: solid;">Example 3: Polymorphic Cloning<br></blockquote><div>If
you have polymorphic cloning, you have to have or your clone function=20
virtual, otherwise you will call the base class' clone from the base=20
pointer/reference. You mention macros as downside again, but even your=20
virtual function example doesn't have any...<br></div><br>So sorry but=20
-1. Mixins are dumbed-down versions of multiple=20
inheritance so languages without that can have that functionality, but=20
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 <u>does</u> ne=
ed a few tweaks here and there, but I don't feel mixins are such.<br><br>If
something is missing, the standard "mixin" classes, starting with=20
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 :)<br><=
br>Regards, Robert<br><br>(For crying out loud Google, let me send the mail=
already!)<div dir=3D"ltr"><br></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_509_8787223.1377647974124--
.
Author: Sean Middleditch <sean.middleditch@gmail.com>
Date: Tue, 27 Aug 2013 17:13:44 -0700 (PDT)
Raw View
------=_Part_5165_24601127.1377648824902
Content-Type: text/plain; charset=ISO-8859-1
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).
--
---
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_5165_24601127.1377648824902
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">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.<div><b=
r></div><div>I would definitely include accessors. The standard three=
to me make perfect sense. private implies only access to the mixin m=
ethods, protected is to the mixin or its mixed-into class/descendants, and =
public means, well, public. Might even allow the using syntax to impl=
y an additional restricted accessibility as per class inheritance, or even =
just reuse that syntax. e.g.</div><div><br></div><div> //=
silly example mixin that might as well just be a regular base class</div><=
div> class m mixin {</div><div> public:</div><div>&=
nbsp; void f() { return 3; } </div><div> };<=
/div><div><br></div><div> class c final : private m {</div><div=
> };</div><div><br></div><div> c v;</div><div> =
; v.f(); // error: private</div><div><br></div><div>I would also clar=
ify that a mixin is not a type. You can't have a pointer to a mixin o=
r such. It's essentially a block of syntactic sugar for a template-li=
ke 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 I=
MO essential to what the core idea of a mixin is or how it could even be im=
plemented reasonably.</div><div><br></div><div>You might consider how these=
could play with constraints, which is a feature that the CRTP method grant=
s today (or once concepts lite are supported, anyway) but mixins do not.</d=
iv><div><br></div><div> mixin foo</div><div> &nbs=
p; requires(Comparable<*this>, is_base_of<base_type, *this>)</d=
iv><div> { ... };</div><div><br></div><div>If this is supporte=
d, 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 sy=
tems have typically provided (e.g. the requirement that get() be provided b=
y any class using the mixin).</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_5165_24601127.1377648824902--
.
Author: Sean Middleditch <sean.middleditch@gmail.com>
Date: Tue, 27 Aug 2013 17:54:43 -0700 (PDT)
Raw View
------=_Part_2496_28141469.1377651283277
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On Tuesday, August 27, 2013 4:59:34 PM UTC-7, R=F3bert D=E1vid 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)=
;=20
> }
> 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=
=20
> reason why you don't write the template parameter out while defining the=
=20
> constructors.
>
That is an incredibly simplistic example of the CRTP mixin pattern. Try a=
=20
class that wants to use two mixins which each partially implement some of=
=20
the polymorphic interface of a base. It gets unwieldly, quickly.
=20
> Example 3: Polymorphic Cloning
>>
> If you have polymorphic cloning, you have to have or your clone function=
=20
> virtual, otherwise you will call the base class' clone from the base=20
> pointer/reference. You mention macros as downside again, but even your=20
> virtual function example doesn't have any...
>
> So sorry but -1. Mixins are dumbed-down versions of multiple inheritance=
=20
> so languages without that can have that functionality, but quite=20
> handicapped in a few cases. C++/CX is such a language, so it needs mixins=
,=20
> aka partial classes. There is absolutely no need for mixins in proper C++=
,=20
> as long as you use the language properly. It *does* need a few tweaks=20
> here and there, but I don't feel mixins are such.
>
They aren't just that. C++'s multiple inheritance also does not solve=20
certain problems. Mixins without MI aren't a complete solution. MI isn't=
=20
a complete solution. Heck, mixins with MI probably won't be a complete=20
solution, but it will be more complete at least.
And then there's the weird recursive situations, which granted are very=20
exceptional in a good design, but I've seen come up several time. Example:
struct base {
virtual base& foo() =3D 0;
virtual base& bar() =3D 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,=
=20
???>, base>>
{
int value =3D 5; // note that mixin_bar wants to use mixin_foo's valu=
e,=20
not derived's value
};
Oppose this to a mixin solution:
struct base {
virtual base& foo() =3D 0;
virtual base& foo() =3D 0;
};
There's no way to realistically fill in the ??? part as mixin_bar's Derived=
=20
type is itself dependent on mixin_bar. Again, it's a weird case, and every=
=20
time I've seen it myself I've found other (arguably much better) ways to do=
=20
what I wanted, but it is a general pattern that C++ multiple inheritance=20
and CRTP are not an alternative to mixins. You can't _compose mixins_ with=
=20
CRTP.
=20
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_2496_28141469.1377651283277
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Tuesday, August 27, 2013 4:59:34 PM UTC-7, R=F3bert D=
=E1vid wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div><div>You can do CRTP a lot better:<br></div><div style=3D"border:1=
px solid rgb(187,187,187);word-wrap:break-word;background-color:rgb(250,250=
,250)"><code><div><span style=3D"color:rgb(0,0,136)">template</span><span s=
tyle=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)"><=
</span><span style=3D"color:rgb(0,0,136)">typename</span><span style=3D"col=
or:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">Derived</span><=
span style=3D"color:rgb(102,102,0)">></span><span style=3D"color:rgb(0,0=
,0)"><br></span><span style=3D"color:rgb(0,0,136)">class</span><span style=
=3D"color:rgb(0,0,0)"> smart_ptr_base </span><span style=3D"color:rgb(102,1=
02,0)">{</span><span style=3D"color:rgb(0,0,0)"><br> </span><span sty=
le=3D"color:rgb(0,0,136)">const</span><span style=3D"color:rgb(0,0,0)"> </s=
pan><span style=3D"color:rgb(102,0,102)">Derived</span><span style=3D"color=
:rgb(102,102,0)">&</span><span style=3D"color:rgb(0,0,0)"> </span><span=
style=3D"color:rgb(0,0,136)">self</span><span style=3D"color:rgb(102,102,0=
)">()</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:r=
gb(0,0,136)">const</span><span style=3D"color:rgb(0,0,0)"> </span><span sty=
le=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,0,0)"> </spa=
n><span style=3D"color:rgb(0,0,136)">return</span><span style=3D"color:rgb(=
0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">*</span><span style=3D=
"color:rgb(0,0,0)">static_cast</span><span style=3D"color:rgb(102,102,0)">&=
lt;</span><span style=3D"color:rgb(0,0,136)">const</span><span style=3D"col=
or:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">Derived</span><=
span style=3D"color:rgb(102,102,0)">*>(</span><span style=3D"color:rgb(0=
,0,136)">this</span><span style=3D"color:rgb(102,102,0)">);</span><span sty=
le=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">}</spa=
n><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(0,0,=
136)"><code><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"c=
olor:rgb(0,0,136)">typedef</span><span style=3D"color:rgb(0,0,0)"> </span><=
span style=3D"color:rgb(0,0,136)">decltype</span><span style=3D"color:rgb(1=
02,102,0)">(self.</span><span style=3D"color:rgb(0,0,136)">get</span><span =
style=3D"color:rgb(102,102,0)">())</span><span style=3D"color:rgb(0,0,0)"> =
T;<br></span><span style=3D"color:rgb(0,0,0)"></span></code>public</span><s=
pan style=3D"color:rgb(102,102,0)">:</span><span style=3D"color:rgb(0,0,0)"=
><br> T</span><span style=3D"color:rgb(102,102,0)">&</span><span =
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">opera=
tor</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb=
(102,102,0)">*()</span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(0,0,136)">const</span><span style=3D"color:rgb(0,0,0)"> </spa=
n><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,0=
,0)"> </span><span style=3D"color:rgb(0,0,136)">return</span><span style=3D=
"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">*</span><sp=
an style=3D"color:rgb(0,0,136)">self</span><span style=3D"color:rgb(102,102=
,0)">().</span><span style=3D"color:rgb(0,0,136)">get</span><span style=3D"=
color:rgb(102,102,0)">();</span><span style=3D"color:rgb(0,0,0)"> </span><s=
pan style=3D"color:rgb(102,102,0)">}</span><span style=3D"color:rgb(0,0,0)"=
><br> </span><span style=3D"color:rgb(136,0,0)">// etc.</span><span s=
tyle=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(102,102,0)">}=
;</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rg=
b(0,0,136)">template</span><span style=3D"color:rgb(0,0,0)"> </span><span s=
tyle=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,136)"=
>typename</span><span style=3D"color:rgb(0,0,0)"> T</span><span style=3D"co=
lor:rgb(102,102,0)">></span><span style=3D"color:rgb(0,0,0)"><br></span>=
<span style=3D"color:rgb(0,0,136)">class</span><span style=3D"color:rgb(0,0=
,0)"> my_ptr </span><span style=3D"color:rgb(102,102,0)">:</span><span styl=
e=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">public</s=
pan><span style=3D"color:rgb(0,0,0)"> smart_ptr_base</span><span style=3D"c=
olor:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,0)">my_ptr</sp=
an><span style=3D"color:rgb(0,0,0)"></span><span style=3D"color:rgb(102,102=
,0)">></span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"col=
or:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,0,0)"><br> T</s=
pan><span style=3D"color:rgb(102,102,0)">*</span><span style=3D"color:rgb(0=
,0,0)"> </span><span style=3D"color:rgb(0,0,136)">get</span><span style=3D"=
color:rgb(102,102,0)">()</span><span style=3D"color:rgb(0,0,0)"> </span><sp=
an style=3D"color:rgb(0,0,136)">const</span><span style=3D"color:rgb(0,0,0)=
"> </span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color=
:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">return</span><span =
style=3D"color:rgb(0,0,0)"> raw</span><span style=3D"color:rgb(102,102,0)">=
;</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(1=
02,102,0)">}</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=
=3D"color:rgb(102,102,0)">};</span><span style=3D"color:rgb(0,0,0)"><br></s=
pan></div></code></div>Works
in VS2012 already.. Note: there is no need to write my_ptr<T>,=20
same reason why you don't write the template parameter out while=20
defining the constructors.<br></div></div></blockquote><div><br></div><div>=
That is an incredibly simplistic example of the CRTP mixin pattern. T=
ry a class that wants to use two mixins which each partially implement some=
of the polymorphic interface of a base. It gets unwieldly, quickly.<=
/div><div> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px=
0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-widt=
h:1px;border-left-style:solid">Example 3: Polymorphic Cloning<br></blockquo=
te><div>If
you have polymorphic cloning, you have to have or your clone function=20
virtual, otherwise you will call the base class' clone from the base=20
pointer/reference. You mention macros as downside again, but even your=20
virtual function example doesn't have any...<br></div><br>So sorry but=20
-1. Mixins are dumbed-down versions of multiple=20
inheritance so languages without that can have that functionality, but=20
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 <u>does</u> ne=
ed a few tweaks here and there, but I don't feel mixins are such.<br></div>=
</div></blockquote><div><br></div><div>They aren't just that. C++'s m=
ultiple inheritance also does not solve certain problems. Mixins with=
out MI aren't a complete solution. MI isn't a complete solution. &nbs=
p;Heck, mixins with MI probably won't be a complete solution, but it will b=
e more complete at least.</div><div><br></div><div>And then there's the wei=
rd recursive situations, which granted are very exceptional in a good desig=
n, but I've seen come up several time. Example:</div><div><br></div><=
div> struct base {</div><div> virtual base&a=
mp; foo() =3D 0;<br></div><div> virtual base& bar() =
=3D 0;</div><div> };</div><div><br></div><div> temp=
late <class Derived, class Base></div><div> struct mixin_=
foo : public Base {</div><div> int value;</div><div>&nbs=
p; Derived& foo() override;</div><div> };</div=
><div><br></div><div> template <class Derived, class Base>=
;</div><div> struct mixin_bar : public Base {</div><div> =
void something(int);</div><div> Derived&=
; bar() override {</div><div> something(static_ca=
st<Derived&>(*this).value);</div><div> =
return *this;</div><div> }</div><div> };</di=
v><div><br></div><div> struct derived : publix mixin_foo<der=
ived, mixin_bar<mixin_foo<derived, ???>, base>></div><div>&n=
bsp; {</div><div> int value =3D 5; // note that m=
ixin_bar wants to use mixin_foo's value, not derived's value</div><div>&nbs=
p; };</div><div><br></div><div>Oppose this to a mixin solution:</div>=
<div><br></div><div> struct base {</div><div> &nbs=
p;virtual base& foo() =3D 0;</div><div> virtual base=
& foo() =3D 0;</div><div> };</div><div><br></div><div>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 wha=
t I wanted, but it is a general pattern that C++ multiple inheritance and C=
RTP are not an alternative to mixins. You can't _compose mixins_ with=
CRTP.</div><div> </div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2496_28141469.1377651283277--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Tue, 27 Aug 2013 19:58:27 -0500
Raw View
--001a11c35e1823036604e4f77fca
Content-Type: text/plain; charset=ISO-8859-1
On 27 August 2013 16:14, Sebastian Redl <wasti.redl@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:nevin@eviloverlord.com> (847) 691-1404
--
---
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c35e1823036604e4f77fca
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra">On 27 August 2013 16:14, Sebast=
ian Redl <span dir=3D"ltr"><<a href=3D"mailto:wasti.redl@gmx.net" target=
=3D"_blank">wasti.redl@gmx.net</a>></span> wrote:<br></div><div class=3D=
"gmail_extra">
<div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margi=
n-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0.8ex;border-left-=
width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;paddin=
g-left:1ex">
<div dir=3D"ltr">=3D=3D=3D Mixins (Class Extension Blocks) for C++ =3D=3D=
=3D<br></div></blockquote><div><br></div><div>0. =A0I would get rid of the =
references to how things were written back in the C++03 days. =A0This is fo=
r C++17; it should be solving the things we can't (easily) write with C=
++14 and Concepts Lite.</div>
<div><br></div><div>1. =A0Change the syntax by making the implicit template=
argument explicit, as in:</div><div><br></div><div>template<typename T&=
gt;</div><div>mixin noncopyable</div><div>{ /*... */=A0};</div><div><br></d=
iv>
<div>This gives you a name for the type instantiated (instead of the weird =
decltype(mixin)) and makes it obvious it is templated. =A0While it violates=
DRY (Don't Repeat Yourself), instantiating it should also require spec=
ifying T, as it is more uniform with the rest of the language.</div>
<div>=A0Example 1: Non-Copyable</div><blockquote class=3D"gmail_quote" styl=
e=3D"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0.8ex;bo=
rder-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:so=
lid;padding-left:1ex">
<div dir=3D"ltr">Here's a non-copyable mixin:<br><br><span style=3D"fon=
t-family:'courier new',monospace">mixin noncopyable {<br>=A0 noncop=
yable(const noncopyable&) =3D delete;<br>=A0 noncopyable& operator =
=3D(const noncopyable&) =3D delete;<br>
}<br>class foo {<br>=A0 using mixin noncopyable;<br>};<br></span><br>Here, =
the compiler will fail to generate the copy functions for foo, because<br>t=
hey would have to call the mixin's copy functions, which are deleted.</=
div>
</blockquote><div><br></div><div>For each of the following can you tell me =
if they are intended to be (a) copyable, (b) non-copyable or (c) non-compil=
eable?<br></div><div><br></div><div>struct One {</div><div>=A0 =A0 using mi=
xin noncopyable;</div>
<div>};</div><div><br></div><div>struct Two {</div><div>=A0 =A0 using mixin=
noncopyable;</div><div>=A0 =A0 Two(Two const&) =3D default;</div><div>=
=A0 =A0 Two& operator=3D(Two const&) =3D default;</div><div>};</div=
><div><br></div>
<div>struct Three {</div><div>=A0 =A0 using mixin noncopyable;</div><div>=
=A0 =A0 Three(Three const&) {}</div><div>=A0 =A0 Three& operator=3D=
(Three const&) { return *this; }</div><div>};</div><div><br></div></div=
><div>Anyway, just my initial questions...</div>
-- <br>=A0Nevin ":-)" Liber=A0 <mailto:<a href=3D"mailto:nevin=
@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>>=A0 (847=
) 691-1404
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c35e1823036604e4f77fca--
.
Author: Sean Middleditch <sean.middleditch@gmail.com>
Date: Tue, 27 Aug 2013 17:59:43 -0700 (PDT)
Raw View
------=_Part_2447_26532948.1377651583526
Content-Type: text/plain; charset=ISO-8859-1
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.
--
---
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2447_26532948.1377651583526
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Tuesday, August 27, 2013 5:54:43 PM UTC-7, Sean Middled=
itch wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-=
left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr=
"><div><br></div><div>Oppose this to a mixin solution:</div><div><br></div>=
<div> struct base {</div><div> virtual base&=
amp; foo() =3D 0;</div><div> virtual base& foo() =3D=
0;</div><div> };</div></div></blockquote><div><br></div>And I =
got distracted and cut short writing up that mixin example. <div><br>=
</div><div><div> struct base {</div><div> vi=
rtual base& foo() =3D 0;</div><div> virtual base&=
; bar() =3D 0;</div><div> };</div></div><div><br></div><div>&nb=
sp; struct mixin_foo mixin {</div><div> int value;=
</div><div> auto decltype(*this) foo();</div><div> =
};</div><div><br></div><div><div> struct mixin_bar mixin=
{<br></div><div> void something(int);</div><div> =
auto bar() {</div><div> something(th=
is->value);</div><div> return *this;</div><div=
> }</div><div> };</div><div><br></div><div>&=
nbsp; struct derived : public base</div><div> {</div><div=
> using mixin mixin_foo;</div><div> =
using mixin mixin_bar { using mixin_foo::value; } // sample syntax</div><d=
iv> int value =3D 5;</div><div> };</div></d=
iv><div><br></div><div>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.</div></=
div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2447_26532948.1377651583526--
.
Author: cornedbee@google.com
Date: Wed, 28 Aug 2013 03:44:04 -0700 (PDT)
Raw View
------=_Part_856_25774621.1377686644837
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On Wednesday, August 28, 2013 1:59:34 AM UTC+2, R=F3bert D=E1vid wrote:
>
> =20
> All your example cases can be solved with a good (private or public) base=
=20
> 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;=20
> N3690 at this time)
> class foo {
> foo(const foo&) =3D delete;
> foo& operator=3D(const foo&) =3D delete;
> };
> (Side note: let me point out that noncopyable and noncopyassignable are=
=20
> two different things, although very frequently used together.)
> The only thing is missing (?) is a standard std::noncopyable "mixin": the=
=20
> one above, with a correct name. This solution does not use macros, does n=
ot=20
> 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"=20
> relation. Saying that Foo is-a noncopyable thing isn't worse than Java or=
=20
> C# saying everything is-a Object, so I don't believe it is a misuse of ba=
se=20
> classes. I don't really see how an empty base class can screw up code=20
> generation, maybe with a bad compiler,
>
The very compiler you're using below has bigger member function pointers=20
for classes that use MI. It may not be a big thing, but it's there.
=20
> but in that case you are probably not even using C++11, or if the multipl=
e=20
> inheritance is banned because of policy reasons, then you are asking a=20
> 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)=
;=20
> }
> 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=
=20
> reason why you don't write the template parameter out while defining the=
=20
> 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`=
=20
(even implicitly) at the top level of a class, even inside a decltype. Even=
=20
if you could, at that point the type Derived is incomplete and the get()=20
call would be invalid. And finally, no, you can't omit the template=20
arguments to my_ptr when passing it to the base class, because as=20
[basic.scope.pdecl]p7 says, "The point of declaration for an=20
injected-class-name (Clause 9) is immediately following the opening brace
of the class definition." The opening brace is of course after the base=20
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=
=20
that your "simple" CRTP example is currently not valid C++, and thus not a=
=20
counterargument to my points.
=20
>
> - The CRTP's workings are unintuitive to those introduced to it - there's=
=20
>> a reason it's called "curiously" recurring. In particular, the fact that=
=20
>> Derived is an incomplete type in the body of the CRTP class is a common=
=20
>> stumbling block, and the reason T must be passed along in the above exam=
ple=20
>> instead of determined by examining Derived (e.g. to look at a nested=20
>> typedef). Function type deduction in C++14 can help in some cases, but n=
ot=20
>> all.
>
> - The class name must be repeated, including all its template arguments -=
=20
>> 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=20
still CRTP. I claim that CRTP by its very nature is not intuitive - saying,=
=20
"but using CRTP doesn't need the extra boilerplate that you also complained=
=20
about" doesn't contradict my core argument.
=20
>
> - The interface that the CRTP base uses from the derived class must eithe=
r=20
>> be public, or there must be some friendship between the classes. Specify=
ing=20
>> the entire base class in a friend declaration can be annoying, and=20
>> friending a type alias wasn't possible before C++11, which led to=20
>> workarounds such as iterator_core_access (from Boost.Iterator).
>>
> Well, ok, you are right, but are you trying to give private functionality=
=20
> 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=
=20
through a mixin". What I want is for mixins to be be able to access=20
functionality in the embedding class that users of the embedding class=20
cannot use.
=20
>
> Example 3: Polymorphic Cloning
>>
> If you have polymorphic cloning, you have to have or your clone function=
=20
> virtual, otherwise you will call the base class' clone from the base=20
> pointer/reference.
>
And your point is? The base version is virtual, and therefore functions=20
overriding it are also virtual. I'm not sure what you're saying here.
=20
> You mention macros as downside again, but even your virtual function=20
> example doesn't have any...
>
I mention macros as a possible solution, not as a downside of something.=20
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=
=20
uses macros, and replacing macros by fully-integrated solutions is=20
generally a good thing. I didn't bother to spell this solution out, because=
=20
it should be completely obvious.
=20
>
> So sorry but -1. Mixins are dumbed-down versions of multiple inheritance=
=20
> so languages without that can have that functionality, but quite=20
> handicapped in a few cases.
>
I see mixins as a clean solution to a use case that is currently=20
imperfectly solved in C++ with multiple inheritance and CRTP, or macros. I=
=20
presented the reasons why the current solutions are imperfect. Your=20
counterargument doesn't compile, proving me right on multiple levels (in=20
particular the non-intuitiveness and level of difficulty of the current=20
solution).
=20
> 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=20
underspecified hack to make life easier for the developers of visual form=
=20
designers and other round-tripping code generators.
=20
> There is absolutely no need for mixins in proper C++, as long as you use=
=20
> the language properly. It *does* need a few tweaks here and there, but I=
=20
> don't feel mixins are such.
>
I'm curious to hear what tweaks you think are necessary.
=20
>
> If something is missing, the standard "mixin" classes, starting with=20
> std::non_copyable, std::non_movable, and so on. Call for papers is until=
=20
> 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=
=20
special-purpose workarounds into the language.
=20
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_856_25774621.1377686644837
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Wednesday, August 28, 2013 1:59:34 AM UTC+2, R=
=F3bert D=E1vid wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><div> <br>All your example cases can be solved with a good (p=
rivate or public) base class, I try to show you how:<br><br><blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;borde=
r-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid=
"><div>Example 1: Non-Copyable<br></div></blockquote>It would be better if =
you start from C++11 (or even the current draft; N3690 at this time)<br><di=
v style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;backgroun=
d-color:rgb(250,250,250)"><code><div><span style=3D"color:rgb(0,0,136)">cla=
ss</span><span style=3D"color:rgb(0,0,0)"> foo </span><span style=3D"color:=
rgb(102,102,0)">{</span><span style=3D"color:rgb(0,0,0)"><br> foo</sp=
an><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,=
0,136)">const</span><span style=3D"color:rgb(0,0,0)"> foo</span><span style=
=3D"color:rgb(102,102,0)">&)</span><span style=3D"color:rgb(0,0,0)"> </=
span><span style=3D"color:rgb(102,102,0)">=3D</span><span style=3D"color:rg=
b(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">delete</span><span sty=
le=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"><br>&n=
bsp; foo</span><span style=3D"color:rgb(102,102,0)">&</span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">operator</=
span><span style=3D"color:rgb(102,102,0)">=3D(</span><span style=3D"color:r=
gb(0,0,136)">const</span><span style=3D"color:rgb(0,0,0)"> foo</span><span =
style=3D"color:rgb(102,102,0)">&)</span><span style=3D"color:rgb(0,0,0)=
"> </span><span style=3D"color:rgb(102,102,0)">=3D</span><span style=3D"col=
or:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">delete</span><spa=
n style=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"><=
br></span><span style=3D"color:rgb(102,102,0)">};</span><span style=3D"colo=
r:rgb(0,0,0)"><br></span></div></code></div>(Side
note: let me point out that noncopyable and noncopyassignable are two=20
different things, although very frequently used together.)<br>The only=20
thing is missing (?) is a standard std::noncopyable "mixin": the one=20
above, with a correct name. This solution does not use macros, does not=20
repeat the class name, and does not change the access classifier=20
anywhere.<br>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=20
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=20
screw up code generation, maybe with a bad compiler,</div></div></blockquot=
e><div><br></div><div>The very compiler you're using below has bigger membe=
r function pointers for classes that use MI. It may not be a big thing, but=
it's there.</div><div> </div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div dir=3D"ltr"><div> but in that case=20
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=20
extension because you don't use the whole language..<br><span style=3D"font=
-family:courier new,monospace"></span><br><blockquote class=3D"gmail_quote"=
style=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(2=
04,204,204);border-left-width:1px;border-left-style:solid">Example 2: Repet=
itive Operators (Boost.Operators, Boost.Iterator)<br></blockquote><div><br>=
You can do CRTP a lot better:<br></div><div style=3D"border:1px solid rgb(1=
87,187,187);word-wrap:break-word;background-color:rgb(250,250,250)"><code><=
div><span style=3D"color:rgb(0,0,136)">template</span><span style=3D"color:=
rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)"><</span><span s=
tyle=3D"color:rgb(0,0,136)">typename</span><span style=3D"color:rgb(0,0,0)"=
> </span><span style=3D"color:rgb(102,0,102)">Derived</span><span style=3D"=
color:rgb(102,102,0)">></span><span style=3D"color:rgb(0,0,0)"><br></spa=
n><span style=3D"color:rgb(0,0,136)">class</span><span style=3D"color:rgb(0=
,0,0)"> smart_ptr_base </span><span style=3D"color:rgb(102,102,0)">{</span>=
<span style=3D"color:rgb(0,0,0)"><br> </span><span style=3D"color:rgb=
(0,0,136)">const</span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(102,0,102)">Derived</span><span style=3D"color:rgb(102,102,0)=
">&</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color=
:rgb(0,0,136)">self</span><span style=3D"color:rgb(102,102,0)">()</span><sp=
an style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">co=
nst</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb=
(102,102,0)">{</span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(0,0,136)">return</span><span style=3D"color:rgb(0,0,0)"> </sp=
an><span style=3D"color:rgb(102,102,0)">*</span><span style=3D"color:rgb(0,=
0,0)">static_cast</span><span style=3D"color:rgb(102,102,0)"><</span><sp=
an style=3D"color:rgb(0,0,136)">const</span><span style=3D"color:rgb(0,0,0)=
"> </span><span style=3D"color:rgb(102,0,102)">Derived</span><span style=3D=
"color:rgb(102,102,0)">*>(</span><span style=3D"color:rgb(0,0,136)">this=
</span><span style=3D"color:rgb(102,102,0)">);</span><span style=3D"color:r=
gb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">}</span><span style=
=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(0,0,136)"><code><=
span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,=
136)">typedef</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D=
"color:rgb(0,0,136)">decltype</span><span style=3D"color:rgb(102,102,0)">(s=
elf.</span><span style=3D"color:rgb(0,0,136)">get</span><span style=3D"colo=
r:rgb(102,102,0)">())</span><span style=3D"color:rgb(0,0,0)"> T;<br></span>=
<span style=3D"color:rgb(0,0,0)"></span></code>public</span><span style=3D"=
color:rgb(102,102,0)">:</span><span style=3D"color:rgb(0,0,0)"><br> T=
</span><span style=3D"color:rgb(102,102,0)">&</span><span style=3D"colo=
r:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">operator</span><sp=
an style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">=
*()</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb=
(0,0,136)">const</span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,0,0)"> </span>=
<span style=3D"color:rgb(0,0,136)">return</span><span style=3D"color:rgb(0,=
0,0)"> </span><span style=3D"color:rgb(102,102,0)">*</span><span style=3D"c=
olor:rgb(0,0,136)">self</span><span style=3D"color:rgb(102,102,0)">().</spa=
n><span style=3D"color:rgb(0,0,136)">get</span><span style=3D"color:rgb(102=
,102,0)">();</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"=
color:rgb(102,102,0)">}</span><span style=3D"color:rgb(0,0,0)"><br> <=
/span><span style=3D"color:rgb(136,0,0)">// etc.</span><span style=3D"color=
:rgb(0,0,0)"><br></span><span style=3D"color:rgb(102,102,0)">};</span><span=
style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(0,0,136)">t=
emplate</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color=
:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,136)">typename</sp=
an><span style=3D"color:rgb(0,0,0)"> T</span><span style=3D"color:rgb(102,1=
02,0)">></span><span style=3D"color:rgb(0,0,0)"><br></span><span style=
=3D"color:rgb(0,0,136)">class</span><span style=3D"color:rgb(0,0,0)"> my_pt=
r </span><span style=3D"color:rgb(102,102,0)">:</span><span style=3D"color:=
rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">public</span><span s=
tyle=3D"color:rgb(0,0,0)"> smart_ptr_base</span><span style=3D"color:rgb(10=
2,102,0)"><</span><span style=3D"color:rgb(0,0,0)">my_ptr</span><span st=
yle=3D"color:rgb(0,0,0)"></span><span style=3D"color:rgb(102,102,0)">></=
span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,=
102,0)">{</span><span style=3D"color:rgb(0,0,0)"><br> T</span><span s=
tyle=3D"color:rgb(102,102,0)">*</span><span style=3D"color:rgb(0,0,0)"> </s=
pan><span style=3D"color:rgb(0,0,136)">get</span><span style=3D"color:rgb(1=
02,102,0)">()</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D=
"color:rgb(0,0,136)">const</span><span style=3D"color:rgb(0,0,0)"> </span><=
span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,0,0)=
"> </span><span style=3D"color:rgb(0,0,136)">return</span><span style=3D"co=
lor:rgb(0,0,0)"> raw</span><span style=3D"color:rgb(102,102,0)">;</span><sp=
an style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">=
}</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rg=
b(102,102,0)">};</span><span style=3D"color:rgb(0,0,0)"><br></span></div></=
code></div>Works
in VS2012 already.. Note: there is no need to write my_ptr<T>,=20
same reason why you don't write the template parameter out while=20
defining the constructors.<br></div></div></blockquote><div><br></div><div>=
Nice that it works in VS2012. Have you actually tried instantiating it?</di=
v><div>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 declty=
pe. 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.sc=
ope.pdecl]p7 says, "The point of declaration for an injected-class-name (Cl=
ause 9) is immediately following the opening brace</div><div>of the class d=
efinition." The opening brace is of course after the base class specifier, =
so the injected-class-name doesn't exist there.</div><div>Now you could arg=
ue that these are defects in the standard, but the fact is that your "simpl=
e" CRTP example is currently not valid C++, and thus not a counterargument =
to my points.</div><div> </div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div dir=3D"ltr"><div><br><blockquote class=3D"gmail_quote" style=3D"=
margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204=
);border-left-width:1px;border-left-style:solid">-
The CRTP's workings are unintuitive to those introduced to it - there's
a reason it's called "curiously" recurring. In particular, the fact=20
that Derived is an incomplete type in the body of the CRTP class is a=20
common stumbling block, and the reason T must be passed along in the=20
above example instead of determined by examining Derived (e.g. to look=20
at a nested typedef). Function type deduction in C++14 can help in some=20
cases, but not all.</blockquote><blockquote class=3D"gmail_quote" style=3D"=
margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204=
);border-left-width:1px;border-left-style:solid">-
The class name must be repeated, including all its template arguments -
the injected-class-name is not yet visible in the base specification.<br><=
/blockquote>None of this is true, see above example.<br></div></div></block=
quote><div><br></div><div>Even if above example was valid, that wouldn't ch=
ange 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.</div>=
<div> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div><br><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px =
0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width=
:1px;border-left-style:solid">-
The interface that the CRTP base uses from the derived class must=20
either be public, or there must be some friendship between the classes.=20
Specifying the entire base class in a friend declaration can be=20
annoying, and friending a type alias wasn't possible before C++11, which
led to workarounds such as iterator_core_access (from Boost.Iterator).<br>=
</blockquote>Well,
ok, you are right, but are you trying to give private functionality=20
through a mixin? I fail to see where can that be useful.<br></div></div></b=
lockquote><div><br></div><div>I don't understand what you mean by "trying t=
o 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 th=
e embedding class cannot use.</div><div> </div><blockquote class=3D"gm=
ail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc soli=
d;padding-left: 1ex;"><div dir=3D"ltr"><div><br><blockquote class=3D"gmail_=
quote" style=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color=
:rgb(204,204,204);border-left-width:1px;border-left-style:solid">Example 3:=
Polymorphic Cloning<br></blockquote><div>If
you have polymorphic cloning, you have to have or your clone function=20
virtual, otherwise you will call the base class' clone from the base=20
pointer/reference.</div></div></div></blockquote><div><br></div><div>And yo=
ur point is? The base version is virtual, and therefore functions overridin=
g it are also virtual. I'm not sure what you're saying here.</div><div>&nbs=
p;</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>=
<div> You mention macros as downside again, but even your=20
virtual function example doesn't have any...<br></div></div></div></blockqu=
ote><div><br></div><div>I mention macros as a possible solution, not as a d=
ownside of something. You can define a macro</div><div>#define CLONEABLE(cl=
azz) clazz* clone() const { return new clazz(*this; }</div><div>and put tha=
t 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 thi=
ng. I didn't bother to spell this solution out, because it should be comple=
tely obvious.</div><div> </div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div dir=3D"ltr"><div><div></div><br>So sorry but=20
-1. Mixins are dumbed-down versions of multiple=20
inheritance so languages without that can have that functionality, but=20
quite handicapped in a few cases.</div></div></blockquote><div><br></div><d=
iv>I see mixins as a clean solution to a use case that is currently imperfe=
ctly solved in C++ with multiple inheritance and CRTP, or macros. I present=
ed the reasons why the current solutions are imperfect. Your counterargumen=
t doesn't compile, proving me right on multiple levels (in particular the n=
on-intuitiveness and level of difficulty of the current solution).</div><di=
v> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"=
><div> C++/CX is such a language, so it needs
mixins, aka partial classes.</div></div></blockquote><div><br></div><div>P=
artial classes are not mixins, since they are not reusable. They are an und=
erspecified hack to make life easier for the developers of visual form desi=
gners and other round-tripping code generators.</div><div> </div><bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-l=
eft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div> There is abs=
olutely no need for mixins
in proper C++, as long as you use the language properly. It <u>does</u> ne=
ed a few tweaks here and there, but I don't feel mixins are such.<br></div>=
</div></blockquote><div><br></div><div>I'm curious to hear what tweaks you =
think are necessary.</div><div> </div><blockquote class=3D"gmail_quote=
" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding=
-left: 1ex;"><div dir=3D"ltr"><div><br>If
something is missing, the standard "mixin" classes, starting with=20
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 :)<br><=
br></div></div></blockquote><div><br></div><div>I have absolutely no intere=
st in writing a hurried paper to get a few hacky special-purpose workaround=
s into the language.</div><div> </div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_856_25774621.1377686644837--
.
Author: cornedbee@google.com
Date: Wed, 28 Aug 2013 03:49:16 -0700 (PDT)
Raw View
------=_Part_2943_31764211.1377686956986
Content-Type: text/plain; charset=ISO-8859-1
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.
--
---
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2943_31764211.1377686956986
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Wednesday, August 28, 2013 2:13:44 AM UTC+2, Se=
an Middleditch wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr">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.<div><br></div>=
<div>I would definitely include accessors. The standard three to me m=
ake perfect sense. private implies only access to the mixin methods, =
protected is to the mixin or its mixed-into class/descendants, and public m=
eans, well, public.</div></div></blockquote><div><br></div><div>Is there a =
use-case for things that are accessible to the embedding class but not its =
descendants?</div><div><br></div><div> </div><blockquote class=3D"gmai=
l_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;=
padding-left: 1ex;"><div dir=3D"ltr"><div>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 (th=
ough unlike a templated type, it's still not a type). Spelling all th=
e 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 reason=
ably.<br></div></div></blockquote><div><br></div><div>Yes, that's an excell=
ent point - I should definitely make that more explicit.</div><div> </=
div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex=
;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></di=
v><div><br></div><div>You might consider how these could play with constrai=
nts, which is a feature that the CRTP method grants today (or once concepts=
lite are supported, anyway) but mixins do not.</div><div><br></div><div>&n=
bsp; mixin foo</div><div> requires(Comparable<=
;*this>, is_base_of<base_type, *this>)</div><div> { .=
... };</div><div><br></div><div>If this is supported, then can you overload =
mixins like you can templates?</div></div></blockquote><div><br></div><div>=
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 g=
ood thing.</div><div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2943_31764211.1377686956986--
.
Author: =?UTF-8?Q?R=C3=B3bert_D=C3=A1vid?= <lrdxgm@gmail.com>
Date: Wed, 28 Aug 2013 03:54:17 -0700 (PDT)
Raw View
------=_Part_131_24965425.1377687257485
Content-Type: text/plain; charset=ISO-8859-1
>
>
> 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
--
---
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_131_24965425.1377687257485
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><br><div>That is an incredibly simplistic example of the CRTP mixin pat=
tern. Try a class that wants to use two mixins which each partially i=
mplement some of the polymorphic interface of a base. It gets unwield=
ly, quickly.</div></div></blockquote><div><br>I didn't simplify CRTP as a w=
hole, I just simplified your example to show why I find it as a bad example=
for this argument.<br></div><br><blockquote class=3D"gmail_quote" style=3D=
"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex=
;"><div dir=3D"ltr"><div> They aren't just that. C++'s multiple =
inheritance also does not solve certain problems. Mixins without MI a=
ren'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 c=
omplete at least.</div></div></blockquote><div><br>I disagree: Please show =
me what you can do with mixins but cannot with MI.<br><br></div><blockquote=
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1=
px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></div><div>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:</div>=
<div><br></div><div> struct base {</div><div> &nbs=
p;virtual base& foo() =3D 0;<br></div><div> virtual =
base& bar() =3D 0;</div><div> };</div><div><br></div><div>&=
nbsp; template <class Derived, class Base></div><div> &nb=
sp;struct mixin_foo : public Base {</div><div> int value=
;</div><div> Derived& foo() override;</div><div>&nbs=
p; };</div><div><br></div><div> template <class Derive=
d, class Base></div><div> struct mixin_bar : public Base {</=
div><div> void something(int);</div><div> &=
nbsp;Derived& bar() override {</div><div> som=
ething(static_cast<<wbr>Derived&>(*this).value);</div><div> =
return *this;</div><div> }</div><di=
v> };</div><div><br></div><div> struct derived : pu=
blix mixin_foo<derived, mixin_bar<mixin_foo<derived, ???>, base=
>></div><div> {</div><div> int value =
=3D 5; // note that mixin_bar wants to use mixin_foo's value, not derived's=
value</div><div> };<br> </div></div></blockquote><blockqu=
ote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left=
: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><br></div><div>O=
ppose this to a mixin solution:</div><div><br></div><div> struc=
t base {</div><div> virtual base& foo() =3D 0;</div>=
<div> virtual base& foo() =3D 0;</div><div> &n=
bsp;};</div><div><br></div><div>There's no way to realistically fill in the=
??? part as mixin_bar's Derived type is itself dependent on mixin_bar. Aga=
in, 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 patter=
n that C++ multiple inheritance and CRTP are not an alternative to mixins. =
You can't _compose mixins_ with CRTP.</div></div></blockquote><div><b=
r>How do you want this to be compiled? When is the function inside mixin_ba=
r parsed, and what will be the type of the .value (because without includin=
g it to a class, that name isn't even declared!)<br><br>Regards, Robert<br>=
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_131_24965425.1377687257485--
.
Author: cornedbee@google.com
Date: Wed, 28 Aug 2013 04:06:19 -0700 (PDT)
Raw View
------=_Part_3001_11076263.1377687980005
Content-Type: text/plain; charset=ISO-8859-1
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 <javascript:>>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.
>
--
---
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_3001_11076263.1377687980005
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Wednesday, August 28, 2013 2:58:27 AM UTC+2, Ne=
vin ":-)" Liber wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><div>On 27 August 2013 16:14, Sebastian Redl <span dir=3D"ltr"><=
;<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"qdJoYD1=
0X9UJ">wasti...@gmx.net</a>></span> wrote:<br></div><div>
<div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margi=
n-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0.8ex;border-left-=
width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;paddin=
g-left:1ex">
<div dir=3D"ltr">=3D=3D=3D Mixins (Class Extension Blocks) for C++ =3D=3D=
=3D<br></div></blockquote><div><br></div><div>0. I would get rid of t=
he 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.</div></div></div></div></blockquote><div><br></di=
v><div>That's probably a good idea. I went with noncopyable for the first e=
xample because it's simple and so well-known.</div><div> </div><blockq=
uote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-lef=
t: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"g=
mail_quote">
<div><br></div><div>1. Change the syntax by making the implicit templ=
ate argument explicit, as in:</div><div><br></div><div>template<typename=
T></div><div>mixin noncopyable</div><div>{ /*... */ };</div><div><=
br></div>
<div>This gives you a name for the type instantiated (instead of the weird =
decltype(mixin)) and makes it obvious it is templated. While it viola=
tes DRY (Don't Repeat Yourself), instantiating it should also require speci=
fying T, as it is more uniform with the rest of the language.</div></div></=
div></div></blockquote><div><br></div><div>I really, really don't want this=
.. I agree that the uniformity is a good argument for it, but I also think t=
hat avoiding repeating the class name when pulling in the mixin is a very g=
ood thing that makes it look a lot less hacky, less like the macro approach=
.. (Is that a "reductio-ad-macrum" fallacy?)</div><div>The decltype(mixin) s=
yntax could be replaced by simply specifying that the name of the mixin nam=
es the embedding type inside the mixin. Would that be better? It would be m=
ore concise, and in a way less weird, but it could also be very surprising.=
</div><div><br></div><div>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.</div><div> <br></div><b=
lockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;borde=
r-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=
=3D"gmail_quote">
<div><br></div><div>For each of the following can you tell me if they are i=
ntended to be (a) copyable, (b) non-copyable or (c) non-compileable?<br></d=
iv></div></div></div></blockquote><div><br></div><div>As I said, this is a =
point that still needs some consideration to find the right solution that i=
s intuitive and useful. But my currently preferred solution would result in=
the following:</div><div> </div><blockquote class=3D"gmail_quote" sty=
le=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left=
: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div></div><div><b=
r></div><div>struct One {</div><div> using mixin noncopyable;<=
/div>
<div>};</div></div></div></div></blockquote><div><br></div><div>Not copyabl=
e. The compiler cannot define the implicit functions for One.</div><div>&nb=
sp;</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div=
><div class=3D"gmail_quote"><div><br></div><div>struct Two {</div><div>&nbs=
p; using mixin noncopyable;</div><div> Two(Two const&am=
p;) =3D default;</div><div> Two& operator=3D(Two const&=
;) =3D default;</div><div>};</div></div></div></div></blockquote><div><br><=
/div><div>Whatever happens in the same situation for a noncopyable base - I=
think it compiles, but the functions will be defined as deleted.</div><div=
> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">=
<div><div class=3D"gmail_quote"><div><br></div>
<div>struct Three {</div><div> using mixin noncopyable;</div><=
div> Three(Three const&) {}</div><div> Three&=
amp; operator=3D(Three const&) { return *this; }</div><div>};</div></di=
v></div></div></blockquote><div><br></div><div>This is copyable, unless the=
noncopyable trait suppresses the default constructor, in which case it's n=
ot compileable.</div><div> </div><blockquote class=3D"gmail_quote" sty=
le=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left=
: 1ex;">
</blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_3001_11076263.1377687980005--
.
Author: =?UTF-8?Q?R=C3=B3bert_D=C3=A1vid?= <lrdxgm@gmail.com>
Date: Wed, 28 Aug 2013 04:17:32 -0700 (PDT)
Raw View
------=_Part_1501_10536214.1377688652064
Content-Type: text/plain; charset=ISO-8859-1
>
>
> 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
--
---
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1501_10536214.1377688652064
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><br><div>Nice that it works in VS2012. Have you actually tried instanti=
ating it?</div><div>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 in=
side a decltype. Even if you could, at that point the type Derived is incom=
plete 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-c=
lass-name (Clause 9) is immediately following the opening brace of the clas=
s definition." The opening brace is of course after the base class specifie=
r, so the injected-class-name doesn't exist there.</div><div>Now you could =
argue that these are defects in the standard, but the fact is that your "si=
mple" CRTP example is currently not valid C++, and thus not a counterargume=
nt to my points.</div></div></blockquote><div><br>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 n=
ow and then in being nonstandard, but I think this is a convenient extensio=
n.)<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div> </div><div>Even if above example was valid, that wouldn't ch=
ange 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.</div>=
</div></blockquote><div><br>Instead ditching CRTP for an (in my opinion) in=
fernal, but more intuitive solution, adding more complication to the langua=
ge 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 impr=
ove 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.<br> <br></d=
iv><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;=
border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div> =
;</div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8e=
x;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div dir=3D=
"ltr"><div> </div><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div d=
ir=3D"ltr"><div> There is absolutely no need for mixins
in proper C++, as long as you use the language properly. It <u>does</u> ne=
ed a few tweaks here and there, but I don't feel mixins are such.<br></div>=
</div></blockquote><div><br></div><div>I'm curious to hear what tweaks you =
think are necessary.</div></div></div></blockquote></div></blockquote><div>=
</div><div>Well, this list is the "C++ standard proposals", if people=
didn't think it needs tweaks here and there, it would been deserted long a=
go.<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div> </div><blockquote class=3D"gmail_quote" style=3D"margin:0;ma=
rgin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"lt=
r"><div>If
something is missing, the standard "mixin" classes, starting with=20
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 :)<br><=
/div></div></blockquote><div><br></div><div>I have absolutely no interest i=
n writing a hurried paper to get a few hacky special-purpose workarounds in=
to the language.</div></div></blockquote><div><br>The comment about the dea=
dline was trying to be a joke, the standard 'mixin classes' is still someth=
ing we should have. Having a standard way to disable copy (without the verb=
ose =3D delete syntax) is not "special purpose".<br><br>Regards, Robert</di=
v></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1501_10536214.1377688652064--
.
Author: David Krauss <potswa@gmail.com>
Date: Wed, 28 Aug 2013 04:21:09 -0700 (PDT)
Raw View
------=_Part_1299_10691025.1377688869807
Content-Type: text/plain; charset=ISO-8859-1
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.
--
---
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1299_10691025.1377688869807
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Really what you're describing is another form of inheritan=
ce. Rather than being a superclass or subclass, the mixin is a peer of the =
target.<br><br>The tricky part is deciding the relative order of declaratio=
n 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 yo=
u made it a using declaration rather than a base specifier.)<br><br>Some ne=
w 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-initia=
lizer.<br><br>Recently I suggested inferring member declarations from a con=
cept applied to a template parameter used as a base class. A name that is r=
equired to exist doesn't really need to be considered type-dependent. Appli=
ed to an incomplete class, the principle could help bridge the gap that see=
ms to be causing confusion in the above posts. Not to make a blanket judgme=
nt about this proposal, but CRTP can probably be improved by such relativel=
y minor changes.<br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1299_10691025.1377688869807--
.
Author: =?UTF-8?Q?Klaim_=2D_Jo=C3=ABl_Lamotte?= <mjklaim@gmail.com>
Date: Wed, 28 Aug 2013 13:25:44 +0200
Raw View
--089e012283841776c204e50040ff
Content-Type: text/plain; charset=ISO-8859-1
On Wed, Aug 28, 2013 at 1:21 PM, David Krauss <potswa@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.
--
---
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e012283841776c204e50040ff
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><br><div class=3D"gmail=
_quote">On Wed, Aug 28, 2013 at 1:21 PM, David Krauss <span dir=3D"ltr"><=
;<a href=3D"mailto:potswa@gmail.com" target=3D"_blank">potswa@gmail.com</a>=
></span> wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div dir=3D"ltr">Really what you're desc=
ribing is another form of inheritance. Rather than being a superclass or su=
bclass, the mixin is a peer of the target.<br>
<br></div></blockquote><div><br></div><div>I don't agree at all. Inheri=
tance is about relationship between types. Here it's about injecting co=
de into a type definition. There is no relationship<br>between the mixin an=
d it's use.<br>
It's closer to member object composition, but applied to interfaces.</d=
iv><div>=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">The tricky=
part is deciding the relative order of declaration and initialization of t=
he mixin members. </div>
</blockquote><div><br></div><div>I expect it to be exactly the same as if y=
ou copy-pasted the mixing code into the user class.</div><div>=A0</div><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #c=
cc solid;padding-left:1ex">
<div dir=3D"ltr">C++11 is more sensitive than C++03 was to the declaration =
order of class members, because we have decltype() now. You could define th=
e members at the using declaration, but this is a potential source of error=
s. (Unless you intended this, I'm not sure why you made it a using decl=
aration rather than a base specifier.)<br>
<br></div></blockquote><div><br></div><div>Can you clarify what is the rela=
tionship between decltype and the order of class members?</div><div>=A0</di=
v><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:=
1px #ccc solid;padding-left:1ex">
<div dir=3D"ltr">Some new syntax would be required to run the constructor o=
f the mixin. It would be odd to mention a name from a using declaration in =
a constructor mem-initializer.<br><br></div></blockquote><div><br></div><di=
v>
Maybe you misread, the proposed mixin is not supposed to have a constructor=
.. It's not a type.</div><div>It's a pack of code.</div><div><br></d=
iv></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e012283841776c204e50040ff--
.
Author: cornedbee@google.com
Date: Wed, 28 Aug 2013 04:59:51 -0700 (PDT)
Raw View
------=_Part_23_28773091.1377691191182
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On Wednesday, August 28, 2013 1:17:32 PM UTC+2, R=F3bert D=E1vid 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=20
>> `this` (even implicitly) at the top level of a class, even inside a=20
>> decltype. Even if you could, at that point the type Derived is incomplet=
e=20
>> and the get() call would be invalid. And finally, no, you can't omit the=
=20
>> template arguments to my_ptr when passing it to the base class, because =
as=20
>> [basic.scope.pdecl]p7 says, "The point of declaration for an=20
>> injected-class-name (Clause 9) is immediately following the opening brac=
e=20
>> of the class definition." The opening brace is of course after the base=
=20
>> 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=
=20
>> is that your "simple" CRTP example is currently not valid C++, and thus =
not=20
>> a counterargument to my points.
>>
>
> Yes, of course, it works fine in every way. This was the compiler at hand=
,=20
> and I didn't try in other compilers, didn't think this can be nonstandard=
=20
> (MSVC surprises me every now and then in being nonstandard, but I think=
=20
> this is a convenient extension.)
>
This is really curious, because it doesn't actually compile once you try to=
=20
instantiate it:
http://rise4fun.com/Vcpp/dWWR=20
>
> =20
>> Even if above example was valid, that wouldn't change the fact that it's=
=20
>> still CRTP. I claim that CRTP by its very nature is not intuitive - sayi=
ng,=20
>> "but using CRTP doesn't need the extra boilerplate that you also complai=
ned=20
>> about" doesn't contradict my core argument.
>>
>
> Instead ditching CRTP for an (in my opinion) infernal,
>
I didn't think it was that bad ... ;-)
=20
> but more intuitive solution, adding more complication to the language=20
> 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=
=20
completely unnecessary syntax clutter. That's a good thing, but it doesn't=
=20
really increase the ease of CRTP.
My main objections are:
1) The very nature of the curious recursion in the CRTP makes it=20
unintuitive. Deriving from a class template that you gave the deriving=20
class tied a knot in the brain of every single person I've ever explained=
=20
it to. That includes people I've explained to how Java's IComparable works.=
=20
(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=
=20
do "class foo : public crtp<bar>", and the compiler can't immediately say,=
=20
"This is wrong!". And currently (with the injected-class-name not available=
=20
in the base list), such an error is actually easy to make - just make an=20
error in specifying the template arguments to your own class. Mixins simply=
=20
make this error impossible. (This, by the way, is a big argument for me=20
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=
=20
only class ever to derive from it will be the one named by the Derived=20
argument, because the language doesn't make such a guarantee.
4) The derived type can never be complete, or even partially complete, in=
=20
the CRTP class body. That's just not how the compilation model of C++=20
works. The only way for the embedding class to provide things to the CRTP=
=20
mixin that need to be known in the class definition and not just in the=20
member definitions is via additional template arguments (possibly just one=
=20
that is a traits class containing all the info). This is a major usability=
=20
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,=
=20
when derived from, implicitly gets the deriving class passed as a template=
=20
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=20
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=20
base class until some point in the class definition, so that the base class=
=20
can access at least parts of the deriving class.
I added these extensions. I call them mixins.
=20
> =20
> Well, this list is the "C++ standard proposals", if people didn't think i=
t=20
> needs tweaks here and there, it would been deserted long ago.
>
>
Ah, you were talking about general C++ tweaks. I thought you meant=20
something related to this particular problem domain.
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_23_28773091.1377691191182
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Wednesday, August 28, 2013 1:17:32 PM UTC+2, R=
=F3bert D=E1vid wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.=
8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><br><div>=
Nice that it works in VS2012. Have you actually tried instantiating it?</di=
v><div>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 declty=
pe. 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.sc=
ope.pdecl]p7 says, "The point of declaration for an injected-class-name (Cl=
ause 9) is immediately following the opening brace of the class definition.=
" The opening brace is of course after the base class specifier, so the inj=
ected-class-name doesn't exist there.</div><div>Now you could argue that th=
ese are defects in the standard, but the fact is that your "simple" CRTP ex=
ample is currently not valid C++, and thus not a counterargument to my poin=
ts.</div></div></blockquote><div><br>Yes, of course, it works fine in every=
way. This was the compiler at hand, and I didn't try in other compilers, d=
idn't think this can be nonstandard (MSVC surprises me every now and then i=
n being nonstandard, but I think this is a convenient extension.)<br></div>=
</div></blockquote><div><br></div><div>This is really curious, because it d=
oesn't actually compile once you try to instantiate it:</div><div><a href=
=3D"http://rise4fun.com/Vcpp/dWWR">http://rise4fun.com/Vcpp/dWWR</a> <=
/div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8e=
x;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><br=
></div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8e=
x;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div> =
</div><div>Even if above example was valid, that wouldn't change the fact t=
hat 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.</div></div></blockqu=
ote><div><br>Instead ditching CRTP for an (in my opinion) infernal,</div></=
div></blockquote><div><br></div><div>I didn't think it was that bad ... ;-)=
</div><div> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0=
;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div di=
r=3D"ltr"><div> but more intuitive solution, adding more complication to th=
e language without any real benefit, what about trying to make CRTP more in=
tuitive?</div></div></blockquote><div><br></div><div>Making the injected-cl=
ass-name available in the base class list gets rid of completely unnecessar=
y syntax clutter. That's a good thing, but it doesn't really increase the e=
ase of CRTP.</div><div><br></div><div>My main objections are:</div><div>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 includ=
es people I've explained to how Java's IComparable works. (It's also curiou=
sly recurring, even though it's not a template.)</div><div>2) A CRTP base i=
sn't actually bound to the deriving class. That is, I can do "class foo : p=
ublic crtp<bar>", and the compiler can't immediately say, "This is wr=
ong!". And currently (with the injected-class-name not available in the bas=
e list), such an error is actually easy to make - just make an error in spe=
cifying the template arguments to your own class. Mixins simply make this e=
rror impossible. (This, by the way, is a big argument for me against Nevin'=
s suggestion to make the embedding class argument explicit.)</div><div>3) O=
n 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.</div><div>4) The deriv=
ed type can never be complete, or even partially complete, in the CRTP clas=
s body. That's just not how the compilation model of C++ works. The only wa=
y 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.</div><div>=
<br></div><div>To solve these problems, you would have to add the following=
to C++:</div><div>To solve 1) and 2), there would be a need to create a cl=
ass template that, when derived from, implicitly gets the deriving class pa=
ssed as a template argument. There must not be different way to pass this a=
rgument.</div><div>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 c=
lass.</div><div>To solve 4), there would have to be a way to delay instanti=
ation of the base class until some point in the class definition, so that t=
he base class can access at least parts of the deriving class.</div><div><b=
r></div><div>I added these extensions. I call them mixins.</div><div> =
</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>&n=
bsp;<br></div><div>Well, this list is the "C++ standard proposals", if peop=
le didn't think it needs tweaks here and there, it would been deserted long=
ago.<br><br></div></div></blockquote><div><br></div><div>Ah, you were talk=
ing about general C++ tweaks. I thought you meant something related to this=
particular problem domain.</div><div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_23_28773091.1377691191182--
.
Author: =?UTF-8?Q?R=C3=B3bert_D=C3=A1vid?= <lrdxgm@gmail.com>
Date: Wed, 28 Aug 2013 05:02:38 -0700 (PDT)
Raw View
------=_Part_3089_13674462.1377691358010
Content-Type: text/plain; charset=ISO-8859-2
Content-Transfer-Encoding: quoted-printable
2013. augusztus 28., szerda 13:25:44 UTC+2 id=F5pontban Klaim - Jo=EBl Lamo=
tte=20
a k=F6vetkez=F5t =EDrta:
>
>
>
>
> On Wed, Aug 28, 2013 at 1:21 PM, David Krauss <pot...@gmail.com<javascrip=
t:>
> > wrote:
>
>> Really what you're describing is another form of inheritance. Rather tha=
n=20
>> 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.=20
> Here it's about injecting code into a type definition. There is no=20
> relationship
> between the mixin and it's use.
> It's closer to member object composition, but applied to interfaces.
> =20
>
>> The tricky part is deciding the relative order of declaration and=20
>> initialization of the mixin members.=20
>>
>
> I expect it to be exactly the same as if you copy-pasted the mixing code=
=20
> into the user class.
> =20
>
>> C++11 is more sensitive than C++03 was to the declaration order of class=
=20
>> members, because we have decltype() now. You could define the members at=
=20
>> the using declaration, but this is a potential source of errors. (Unless=
=20
>> you intended this, I'm not sure why you made it a using declaration rath=
er=20
>> than a base specifier.)
>>
>>
> Can you clarify what is the relationship between decltype and the order o=
f=20
> class members?
> =20
>
>> Some new syntax would be required to run the constructor of the mixin. I=
t=20
>> would be odd to mention a name from a using declaration in a constructor=
=20
>> mem-initializer.
>>
>>
> Maybe you misread, the proposed mixin is not supposed to have a=20
> constructor. It's not a type.
>
That's new: In every single language out there, mixin is a type. While C++=
=20
does not have to follow the same path, I think it is a bad idea to have=20
something that is behaved differently than what every programmer with=20
experiences in other languages think. Please don't name it mixin, if this=
=20
says like it.
It's a pack of code.
>
>
Soooo.. a macro? What's *wrong* with macros, besides the awkward "generally=
=20
good idea not to use them" argument? How about this macro-based solution to=
=20
the problem:
struct base {
virtual base& foo() =3D 0;
virtual base& bar() =3D 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 =3D 5; //Meh - improvement area.
};
Regards, Robert
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_3089_13674462.1377691358010
Content-Type: text/html; charset=ISO-8859-2
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>2013. augusztus 28., szerda 13:25:44 UTC+2 id=F5po=
ntban Klaim - Jo=EBl Lamotte a k=F6vetkez=F5t =EDrta:<blockquote class=3D"g=
mail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc sol=
id;padding-left: 1ex;"><div dir=3D"ltr"><br><div><br><br><div class=3D"gmai=
l_quote">On Wed, Aug 28, 2013 at 1:21 PM, David Krauss <span dir=3D"ltr">&l=
t;<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"RVHlV4=
NnjK8J">pot...@gmail.com</a>></span> wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div dir=3D"ltr">Really what you're describi=
ng is another form of inheritance. Rather than being a superclass or subcla=
ss, the mixin is a peer of the target.<br>
<br></div></blockquote><div><br></div><div>I don't agree at all. Inheritanc=
e is about relationship between types. Here it's about injecting code into =
a type definition. There is no relationship<br>between the mixin and it's u=
se.<br>
It's closer to member object composition, but applied to interfaces.</div><=
div> </div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8e=
x;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">The tricky =
part is deciding the relative order of declaration and initialization of th=
e mixin members. </div>
</blockquote><div><br></div><div>I expect it to be exactly the same as if y=
ou copy-pasted the mixing code into the user class.</div><div> </div><=
blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px=
#ccc solid;padding-left:1ex">
<div dir=3D"ltr">C++11 is more sensitive than C++03 was to the declaration =
order of class members, because we have decltype() now. You could define th=
e members at the using declaration, but this is a potential source of error=
s. (Unless you intended this, I'm not sure why you made it a using declarat=
ion rather than a base specifier.)<br>
<br></div></blockquote><div><br></div><div>Can you clarify what is the rela=
tionship between decltype and the order of class members?</div><div> <=
/div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-le=
ft:1px #ccc solid;padding-left:1ex">
<div dir=3D"ltr">Some new syntax would be required to run the constructor o=
f the mixin. It would be odd to mention a name from a using declaration in =
a constructor mem-initializer.<br><br></div></blockquote><div><br></div><di=
v>
Maybe you misread, the proposed mixin is not supposed to have a constructor=
.. It's not a type.</div></div></div></div></blockquote><div><br>That's new:=
In every single language out there, mixin is a type. While C++ does not ha=
ve 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 othe=
r languages think. Please don't name it mixin, if this says like it.<br><br=
></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.=
8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><=
div class=3D"gmail_quote"><div>It's a pack of code.</div><div><br></div></d=
iv></div></div></blockquote><div><br>Soooo.. a macro? What's <i>wrong</i> w=
ith macros, besides the awkward "generally good idea not to use them" argum=
ent? How about this macro-based solution to the problem:<br><br><div class=
=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); border-colo=
r: rgb(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: b=
reak-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span=
style=3D"color: #008;" class=3D"styled-by-prettify">struct</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">base</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br> </span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">virtual</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prett=
ify">base</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&=
amp;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> foo</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">()</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #066;=
" class=3D"styled-by-prettify">0</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br> </span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">virtual</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">base</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&a=
mp;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> bar</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">()</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #066;=
" class=3D"styled-by-prettify">0</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">};</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br><br></span><span style=3D"color: #800;" class=3D"styled-by-prettify">#=
define</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> MIX=
IN_FOO </span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">\</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&n=
bsp; </span><span style=3D"color: #008;" class=3D"styled-by-prettify">int</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> value</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">\</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br> __THIS_CLASS__</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> foo</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">()</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"s=
tyled-by-prettify">override</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br><br></span><span style=3D"color: #800;" class=3D"styled-by-pret=
tify">#define</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> MIXIN BAR </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">\</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&=
nbsp; </span><span style=3D"color: #008;" class=3D"styled-by-prettify">void=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> something=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">int</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">);</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">\</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br> __THIS_CLASS__</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">&</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> bar</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">()</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">override</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">\</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br> something=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify">value</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">);</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">\</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"><br> </span><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">return</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">*</span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">this</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">\</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"><br> </span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br><br></span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">struct</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> derived </span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">:</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">public</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">base</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">{=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br> =
MIXIN_FOO<br> MIXIN_BAR<br> value </span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=3D=
"styled-by-prettify">5</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: #800;" class=3D"styled-by-prettify">//Meh =
- improvement area.</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">};</span></div></code></div><br><br>Regards, Robert<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_3089_13674462.1377691358010--
.
Author: cornedbee@google.com
Date: Wed, 28 Aug 2013 05:07:11 -0700 (PDT)
Raw View
------=_Part_23_29885889.1377691631111
Content-Type: text/plain; charset=ISO-8859-1
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.
--
---
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_23_29885889.1377691631111
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Wednesday, August 28, 2013 1:21:09 PM UTC+2, Da=
vid Krauss wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr">Really what you're describing is another form of inheritance. Rather th=
an being a superclass or subclass, the mixin is a peer of the target.<br></=
div></blockquote><div><br></div><div>Kind of, but not really, because a mix=
in is not a type. It's a collection of declarations and definitions to be i=
njected into a real type.</div><div> </div><blockquote class=3D"gmail_=
quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pa=
dding-left: 1ex;"><div dir=3D"ltr"><br>The tricky part is deciding the rela=
tive 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, b=
ecause we have decltype() now. You could define the members at the using de=
claration, but this is a potential source of errors. (Unless you intended t=
his, I'm not sure why you made it a using declaration rather than a base sp=
ecifier.)<br></div></blockquote><div><br></div><div>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 emb=
edder, and some thiings in the embedder can use the stuff in the mixin.</di=
v><div> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0;mar=
gin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D=
"ltr"><br>Some new syntax would be required to run the constructor of the m=
ixin. It would be odd to mention a name from a using declaration in a const=
ructor mem-initializer.<br></div></blockquote><div><br></div><div>It's not =
a using declaration. It's a using mixin directive. ;-)</div><div>Yes, mixin=
s 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 memb=
er variables of the class. I don't see why that's unintuitive, and especial=
ly not how new syntax would be any better.</div><div> </div><blockquot=
e class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: =
1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><br>Recently I suggeste=
d inferring member declarations from a concept applied to a template parame=
ter used as a base class. A name that is required to exist doesn't really n=
eed to be considered type-dependent. Applied to an incomplete class, the pr=
inciple 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.<br></div></block=
quote><div> </div><div>Using concepts on the parameter of a CRTP base =
- interesting idea. I'm not sure how concept checks would work for incomple=
te types, though.</div><div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_23_29885889.1377691631111--
.
Author: =?ISO-8859-1?Q?Daniel_Kr=FCgler?= <daniel.kruegler@gmail.com>
Date: Wed, 28 Aug 2013 14:08:01 +0200
Raw View
2013/8/28 R=F3bert D=E1vid <lrdxgm@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 disadvantage=
s:
- 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
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Wed, 28 Aug 2013 15:12:53 +0300
Raw View
--001a11c3d73cb24d7f04e500e8c9
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On 28 August 2013 15:02, R=F3bert D=E1vid <lrdxgm@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-base=
d
> 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.
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--001a11c3d73cb24d7f04e500e8c9
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><br><div class=3D"gmail=
_quote">On 28 August 2013 15:02, R=F3bert D=E1vid <span dir=3D"ltr"><<a =
href=3D"mailto:lrdxgm@gmail.com" target=3D"_blank">lrdxgm@gmail.com</a>>=
</span> wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div dir=3D"ltr">It's a pack of code.<di=
v class=3D"im"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-l=
eft:0.8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir=3D"ltr"><div><div class=3D"gmail_quote"><div><br></div></div></div=
></div></blockquote></div><div><br>Soooo.. a macro? What's <i>wrong</i>=
with macros, besides the awkward "generally good idea not to use them=
" argument? How about this macro-based solution to the problem:<br>
<br></div></div></blockquote><div><br></div><div>Seriously? What's real=
ly wrong with macros is that they don't obey scopes, and error reportin=
g when you make a mistake<br>in a macro definition is rather dismal. Debugg=
ing macro-heavy code can also be rather frustratingly hard. The<br>
</div><div>"generally good idea not to use them" is not just a ra=
ndom statement, it's based on the downsides of macros,<br>and it's =
not just grandstanding from the top of a high horse.<br></div></div><br>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c3d73cb24d7f04e500e8c9--
.
Author: =?UTF-8?Q?R=C3=B3bert_D=C3=A1vid?= <lrdxgm@gmail.com>
Date: Wed, 28 Aug 2013 05:30:21 -0700 (PDT)
Raw View
------=_Part_222_14317873.1377693021888
Content-Type: text/plain; charset=ISO-8859-1
> 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
--
---
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_222_14317873.1377693021888
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">The macro=
expands to the declaration of the two special members above, and in
<br>some cases includes the access specifier. It has the following disadvan=
tages:
<br>- Uses the preprocessor.
<br></blockquote><div>Preprocessor is part of C++. What's <i>wrong</i> with=
using a C++ feature? Yes, the preprocessor is bad. Can't we improve it?<br=
><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left=
: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">- Repeats the class=
name.
<br></blockquote><div>Can be fixed with a __THIS_CLASS__-ish macro, the sam=
e way there is __FUNCTION__ or __PRETTY_FUNCTION__ in some implementations.=
<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">- Changes the ac=
cess specifier. OR Must be placed in private section.<br></blockquote><div>=
Probably can be fixed also. <br></div><div> </div><blockquote class=3D=
"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc s=
olid;padding-left: 1ex;">I'm not at all convinced that macros are an equiva=
lent solution and I
<br>would rather prefer to stay away from it, where this is possible.
<br></blockquote><div><br>But they are equal to the "just a bunch of code" =
mixins. Obviously then they are not that.<br><br>Regards, Robert<br></div><=
/div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_222_14317873.1377693021888--
.
Author: cornedbee@google.com
Date: Wed, 28 Aug 2013 05:30:47 -0700 (PDT)
Raw View
------=_Part_2652_13566579.1377693047893
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On Wednesday, August 28, 2013 2:02:38 PM UTC+2, R=F3bert D=E1vid wrote:
>
>
> That's new: In every single language out there, mixin is a type. While C+=
+=20
> does not have to follow the same path, I think it is a bad idea to have=
=20
> something that is behaved differently than what every programmer with=20
> experiences in other languages think. Please don't name it mixin, if this=
=20
> 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=20
mixin functionality.
Rust has traits, which are like interfaces, but mostly used for bounds in=
=20
generics.
I could call the new feature "traits", but that name is already used by the=
=20
standard library (iterator_traits, char_traits), and reusing it would be=20
far more confusing than taking the already-muddled name mixins.
=20
>
> It's a pack of code.
>>
>>
> Soooo.. a macro? What's *wrong* with macros, besides the awkward=20
> "generally good idea not to use them" argument?
>
Failure to integrate into the language. Failure to respect namespaces.=20
Failure to understand templates passed as arguments (have you ever found=20
the , between your template arguments being interpreted as separating your=
=20
macro arguments?). Failure to provide decent debugger support on many=20
platforms. Need I go on?
=20
> How about this macro-based solution to the problem:
>
> struct base {
> virtual base& foo() =3D 0;
> virtual base& bar() =3D 0;
> };
>
> #define MIXIN_FOO \
>
Argh, line continuations! Completely different from the rest of C++?
=20
>
> int value; \
> __THIS_CLASS__& foo() override;
>
What if value is not supposed to be public? What about foo? Where does=20
__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=20
language is lacking.
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_2652_13566579.1377693047893
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Wednesday, August 28, 2013 2:02:38 PM UTC+2, R=
=F3bert D=E1vid wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><br><div>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 ba=
d idea to have something that is behaved differently than what every progra=
mmer with experiences in other languages think. Please don't name it mixin,=
if this says like it.<br></div></div></blockquote><div><br></div><div>D's =
template mixins are not types. (They are very close to macros.)</div><div>S=
cala has mixins, but calls them traits.</div><div>PHP has what I want, but =
calls it traits.</div><div>Ruby's modules provide the same functionality, b=
ut it's referred to as mixin functionality.</div><div>Rust has traits, whic=
h are like interfaces, but mostly used for bounds in generics.</div><div><b=
r></div><div>I could call the new feature "traits", but that name is alread=
y used by the standard library (iterator_traits, char_traits), and reusing =
it would be far more confusing than taking the already-muddled name mixins.=
</div><div> <br></div><blockquote class=3D"gmail_quote" style=3D"margi=
n: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><di=
v dir=3D"ltr"><div><br></div><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div d=
ir=3D"ltr"><div><div class=3D"gmail_quote"><div>It's a pack of code.</div><=
div><br></div></div></div></div></blockquote><div><br>Soooo.. a macro? What=
's <i>wrong</i> with macros, besides the awkward "generally good idea not t=
o use them" argument?</div></div></blockquote><div><br></div><div>Failure t=
o integrate into the language. Failure to respect namespaces. Failure to un=
derstand templates passed as arguments (have you ever found the , between y=
our template arguments being interpreted as separating your macro arguments=
?). Failure to provide decent debugger support on many platforms. Need I go=
on?</div><div> </div><blockquote class=3D"gmail_quote" style=3D"margi=
n: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><di=
v dir=3D"ltr"><div> How about this macro-based solution to the problem:<br>=
<br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,18=
7,187);border-style:solid;border-width:1px;word-wrap:break-word"><code><div=
><span style=3D"color:#008">struct</span><span style=3D"color:#000"> </span=
><span style=3D"color:#008">base</span><span style=3D"color:#000"> </span><=
span style=3D"color:#660">{</span><span style=3D"color:#000"><br> </s=
pan><span style=3D"color:#008">virtual</span><span style=3D"color:#000"> </=
span><span style=3D"color:#008">base</span><span style=3D"color:#660">&=
</span><span style=3D"color:#000"> foo</span><span style=3D"color:#660">()<=
/span><span style=3D"color:#000"> </span><span style=3D"color:#660">=3D</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#066">0</span><s=
pan style=3D"color:#660">;</span><span style=3D"color:#000"><br> </sp=
an><span style=3D"color:#008">virtual</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#008">base</span><span style=3D"color:#660">&<=
/span><span style=3D"color:#000"> bar</span><span style=3D"color:#660">()</=
span><span style=3D"color:#000"> </span><span style=3D"color:#660">=3D</spa=
n><span style=3D"color:#000"> </span><span style=3D"color:#066">0</span><sp=
an style=3D"color:#660">;</span><span style=3D"color:#000"><br></span><span=
style=3D"color:#660">};</span><span style=3D"color:#000"><br><br></span><s=
pan style=3D"color:#800">#define</span><span style=3D"color:#000"> MIXIN_FO=
O </span><span style=3D"color:#660">\</span></div></code></div></div>=
</div></blockquote><div><br></div><div>Argh, line continuations! Completely=
different from the rest of C++?</div><div> </div><blockquote class=3D=
"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc s=
olid;padding-left: 1ex;"><div dir=3D"ltr"><div><div style=3D"background-col=
or:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border=
-width:1px;word-wrap:break-word"><code><div><span style=3D"color:#000"><br>=
</span><span style=3D"color:#008">int</span><span style=3D"color:#00=
0"> value</span><span style=3D"color:#660">;</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#660">\</span><span style=3D"color:#000"><b=
r> __THIS_CLASS__</span><span style=3D"color:#660">&</span><span =
style=3D"color:#000"> foo</span><span style=3D"color:#660">()</span><span s=
tyle=3D"color:#000"> </span><span style=3D"color:#008">override</span><span=
style=3D"color:#660">;</span></div></code></div></div></div></blockquote><=
div><br></div><div>What if value is not supposed to be public? What about f=
oo? Where does __THIS_CLASS__ come from?</div><blockquote class=3D"gmail_qu=
ote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padd=
ing-left: 1ex;"><div dir=3D"ltr"><div><div style=3D"background-color:rgb(25=
0,250,250);border-color:rgb(187,187,187);border-style:solid;border-width:1p=
x;word-wrap:break-word"><code><div><span style=3D"color:#000"><br></span><s=
pan style=3D"color:#008">struct</span><span style=3D"color:#000"> derived <=
/span><span style=3D"color:#660">:</span><span style=3D"color:#000"> </span=
><span style=3D"color:#008">public</span><span style=3D"color:#000"> </span=
><span style=3D"color:#008">base</span><span style=3D"color:#000"><br></spa=
n><span style=3D"color:#660">{</span><span style=3D"color:#000"><br> =
MIXIN_FOO<br> MIXIN_BAR<br></span></div></code></div></div></div></bl=
ockquote><div><br></div><div>What is the active access specifier here?</div=
><div><br></div><div>Macros are a hack. Every use of macros indicates a pla=
ce where the core language is lacking.</div><div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2652_13566579.1377693047893--
.
Author: =?UTF-8?Q?Klaim_=2D_Jo=C3=ABl_Lamotte?= <mjklaim@gmail.com>
Date: Wed, 28 Aug 2013 14:35:24 +0200
Raw View
--001a11c308e037a95c04e501390c
Content-Type: text/plain; charset=ISO-8859-1
Another question:
would mixin composition be allowed?
mixin K
{
using mixin U;
using mixin W;
};
--
---
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c308e037a95c04e501390c
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Another question:<br>would mixin composition be allowed?<b=
r><br>mixin K<br>{<div>=A0 =A0 using mixin U;<br>=A0 =A0 using mixin W;<br>=
};<br><br><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c308e037a95c04e501390c--
.
Author: =?UTF-8?Q?R=C3=B3bert_D=C3=A1vid?= <lrdxgm@gmail.com>
Date: Wed, 28 Aug 2013 05:44:01 -0700 (PDT)
Raw View
------=_Part_133_33278058.1377693841709
Content-Type: text/plain; charset=ISO-8859-2
Content-Transfer-Encoding: quoted-printable
2013. augusztus 28., szerda 14:30:47 UTC+2 id=F5pontban corn...@google.com =
a=20
k=F6vetkez=F5t =EDrta:
>
>
>
> On Wednesday, August 28, 2013 2:02:38 PM UTC+2, R=F3bert D=E1vid wrote:
>>
>>
>> That's new: In every single language out there, mixin is a type. While=
=20
>> C++ does not have to follow the same path, I think it is a bad idea to h=
ave=20
>> something that is behaved differently than what every programmer with=20
>> experiences in other languages think. Please don't name it mixin, if thi=
s=20
>> 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=20
> mixin functionality.
> Rust has traits, which are like interfaces, but mostly used for bounds in=
=20
> generics.
>
> I could call the new feature "traits", but that name is already used by=
=20
> the standard library (iterator_traits, char_traits), and reusing it would=
=20
> be far more confusing than taking the already-muddled name mixins.
> =20
>
>>
>> It's a pack of code.
>>>
>>>
>> Soooo.. a macro? What's *wrong* with macros, besides the awkward=20
>> "generally good idea not to use them" argument?
>>
>
> Failure to integrate into the language. Failure to respect namespaces.=20
> Failure to understand templates passed as arguments (have you ever found=
=20
> the , between your template arguments being interpreted as separating you=
r=20
> macro arguments?). Failure to provide decent debugger support on many=20
> platforms. Need I go on?
> =20
>
>> How about this macro-based solution to the problem:
>>
>> struct base {
>> virtual base& foo() =3D 0;
>> virtual base& bar() =3D 0;
>> };
>>
>> #define MIXIN_FOO \
>>
>
> Argh, line continuations! Completely different from the rest of C++?
> =20
>
>>
>> int value; \
>> __THIS_CLASS__& foo() override;
>>
>
> What if value is not supposed to be public? What about foo? Where does=20
> __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=
=20
> language is lacking.
>
>
Macros are part of the language. It will not go away. We have to live with=
=20
this fact.
But with *improvements* (sorry, but everyone seem to miss that this is my=
=20
point) it could also work in the place of mixins. Same way as MI / CRTP=20
could. Either way, with "small" standard changes you could have what you=20
need (with different syntax), and the language doesn't need an extra=20
~hundred pages describing every single current feature's interaction with=
=20
the new mixin feature.
Regards, Robert
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_133_33278058.1377693841709
Content-Type: text/html; charset=ISO-8859-2
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>2013. augusztus 28., szerda 14:30:47 UTC+2 id=F5po=
ntban corn...@google.com a k=F6vetkez=F5t =EDrta:<blockquote class=3D"gmail=
_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;p=
adding-left: 1ex;"><div dir=3D"ltr"><br><br>On Wednesday, August 28, 2013 2=
:02:38 PM UTC+2, R=F3bert D=E1vid wrote:<blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:=
1ex"><div dir=3D"ltr"><br><div>That's new: In every single language out the=
re, mixin is a type. While C++ does not have to follow the same path, I thi=
nk 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 n=
ame it mixin, if this says like it.<br></div></div></blockquote><div><br></=
div><div>D's template mixins are not types. (They are very close to macros.=
)</div><div>Scala has mixins, but calls them traits.</div><div>PHP has what=
I want, but calls it traits.</div><div>Ruby's modules provide the same fun=
ctionality, but it's referred to as mixin functionality.</div><div>Rust has=
traits, which are like interfaces, but mostly used for bounds in generics.=
</div><div><br></div><div>I could call the new feature "traits", but that n=
ame 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.</div><div> <br></div><blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:=
1ex"><div dir=3D"ltr"><div><br></div><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex=
"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>It's a pack of code=
..</div><div><br></div></div></div></div></blockquote><div><br>Soooo.. a mac=
ro? What's <i>wrong</i> with macros, besides the awkward "generally good id=
ea not to use them" argument?</div></div></blockquote><div><br></div><div>F=
ailure to integrate into the language. Failure to respect namespaces. Failu=
re to understand templates passed as arguments (have you ever found the , b=
etween your template arguments being interpreted as separating your macro a=
rguments?). Failure to provide decent debugger support on many platforms. N=
eed I go on?</div><div> </div><blockquote class=3D"gmail_quote" style=
=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"=
><div dir=3D"ltr"><div> How about this macro-based solution to the problem:=
<br><br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(18=
7,187,187);border-style:solid;border-width:1px;word-wrap:break-word"><code>=
<div><span style=3D"color:#008">struct</span><span style=3D"color:#000"> </=
span><span style=3D"color:#008">base</span><span style=3D"color:#000"> </sp=
an><span style=3D"color:#660">{</span><span style=3D"color:#000"><br> =
</span><span style=3D"color:#008">virtual</span><span style=3D"color:#000"=
> </span><span style=3D"color:#008">base</span><span style=3D"color:#660">&=
amp;</span><span style=3D"color:#000"> foo</span><span style=3D"color:#660"=
>()</span><span style=3D"color:#000"> </span><span style=3D"color:#660">=3D=
</span><span style=3D"color:#000"> </span><span style=3D"color:#066">0</spa=
n><span style=3D"color:#660">;</span><span style=3D"color:#000"><br> =
</span><span style=3D"color:#008">virtual</span><span style=3D"color:#000">=
</span><span style=3D"color:#008">base</span><span style=3D"color:#660">&a=
mp;</span><span style=3D"color:#000"> bar</span><span style=3D"color:#660">=
()</span><span style=3D"color:#000"> </span><span style=3D"color:#660">=3D<=
/span><span style=3D"color:#000"> </span><span style=3D"color:#066">0</span=
><span style=3D"color:#660">;</span><span style=3D"color:#000"><br></span><=
span style=3D"color:#660">};</span><span style=3D"color:#000"><br><br></spa=
n><span style=3D"color:#800">#define</span><span style=3D"color:#000"> MIXI=
N_FOO </span><span style=3D"color:#660">\</span></div></code></div></=
div></div></blockquote><div><br></div><div>Argh, line continuations! Comple=
tely different from the rest of C++?</div><div> </div><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc =
solid;padding-left:1ex"><div dir=3D"ltr"><div><div style=3D"background-colo=
r:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-=
width:1px;word-wrap:break-word"><code><div><span style=3D"color:#000"><br>&=
nbsp; </span><span style=3D"color:#008">int</span><span style=3D"color:#000=
"> value</span><span style=3D"color:#660">;</span><span style=3D"color:#000=
"> </span><span style=3D"color:#660">\</span><span style=3D"color:#000"><br=
> __THIS_CLASS__</span><span style=3D"color:#660">&</span><span s=
tyle=3D"color:#000"> foo</span><span style=3D"color:#660">()</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#008">override</span><span =
style=3D"color:#660">;</span></div></code></div></div></div></blockquote><d=
iv><br></div><div>What if value is not supposed to be public? What about fo=
o? Where does __THIS_CLASS__ come from?</div><blockquote class=3D"gmail_quo=
te" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-=
left:1ex"><div dir=3D"ltr"><div><div style=3D"background-color:rgb(250,250,=
250);border-color:rgb(187,187,187);border-style:solid;border-width:1px;word=
-wrap:break-word"><code><div><span style=3D"color:#000"><br></span><span st=
yle=3D"color:#008">struct</span><span style=3D"color:#000"> derived </span>=
<span style=3D"color:#660">:</span><span style=3D"color:#000"> </span><span=
style=3D"color:#008">public</span><span style=3D"color:#000"> </span><span=
style=3D"color:#008">base</span><span style=3D"color:#000"><br></span><spa=
n style=3D"color:#660">{</span><span style=3D"color:#000"><br> MIXIN_=
FOO<br> MIXIN_BAR<br></span></div></code></div></div></div></blockquo=
te><div><br></div><div>What is the active access specifier here?</div><div>=
<br></div><div>Macros are a hack. Every use of macros indicates a place whe=
re the core language is lacking.</div><div><br></div></div></blockquote><di=
v><br>Macros are part of the language. It will not go away. We have to live=
with this fact.<br>But with <font size=3D"6"><u><b>improvements</b></u></f=
ont> (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 synt=
ax), and the language doesn't need an extra ~hundred pages describing every=
single current feature's interaction with the new mixin feature.<br><br>Re=
gards, Robert<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_133_33278058.1377693841709--
.
Author: Maurice Bos <m-ou.se@m-ou.se>
Date: Wed, 28 Aug 2013 14:44:42 +0200
Raw View
--001a11c34b48a539e404e5015b96
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
2013/8/28 R=F3bert D=E1vid <lrdxgm@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.
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--001a11c34b48a539e404e5015b96
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><br><div class=3D"gmail=
_quote">2013/8/28 R=F3bert D=E1vid <span dir=3D"ltr"><<a href=3D"mailto:=
lrdxgm@gmail.com" target=3D"_blank">lrdxgm@gmail.com</a>></span><br><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #c=
cc solid;padding-left:1ex">
<div dir=3D"ltr"><br><div>Can be fixed with a __THIS_CLASS__-ish macro, the=
same way there is __FUNCTION__ or __PRETTY_FUNCTION__ in some implementati=
ons.<br><br></div><br></div></blockquote><div><br>__func__ and __PRETTY_FUN=
CTION__ are 'magic' variables of const char array types, they are n=
ot macro's. The preprocessor has nothing to do with these two variables=
..<br>
</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c34b48a539e404e5015b96--
.
Author: cornedbee@google.com
Date: Wed, 28 Aug 2013 05:52:11 -0700 (PDT)
Raw View
------=_Part_2000_28105055.1377694331531
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On Wednesday, August 28, 2013 2:35:24 PM UTC+2, Klaim - Jo=EBl Lamotte wrot=
e:
> Another question:
> would mixin composition be allowed?
>
> mixin K
> {
> using mixin U;
> using mixin W;
> };
>
Yes, as stated in my proposal:
"Mixins can contain every kind of declaration that classes can, including=
=20
inner types, data members, and *more mixin directives*."
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_2000_28105055.1377694331531
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, August 28, 2013 2:35:24 PM UTC+2, Klaim - Jo=
=EBl Lamotte wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin: 0=
;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div di=
r=3D"ltr">Another question:<br>would mixin composition be allowed?<br><br>m=
ixin K<br>{<div> using mixin U;<br> using mixin W=
;<br>};<br></div></div></blockquote><div><br></div><div>Yes, as stated in m=
y proposal:</div><div>"Mixins can contain every kind of declaration that cl=
asses can, including inner types, data members, and <b>more mixin dire=
ctives</b>."<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2000_28105055.1377694331531--
.
Author: cornedbee@google.com
Date: Wed, 28 Aug 2013 05:59:47 -0700 (PDT)
Raw View
------=_Part_57_24001336.1377694787741
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On Wednesday, August 28, 2013 2:44:01 PM UTC+2, R=F3bert D=E1vid wrote:
>
> Macros are a hack. Every use of macros indicates a place where the core=
=20
>> language is lacking.
>>
>>
> Macros are part of the language. It will not go away. We have to live wit=
h=20
> this fact.
>
But that doesn't mean we have to celebrate it. Inline functions, real=20
constants, templates, now constexpr functions, are all replacing uses of=20
macros. Attributes replace pragmas to some extent. Modules are in=20
development to subsume/replace/obsolete includes. We cannot ever get rid of=
=20
the preprocessor, but we want to relegate it to exotic uses and backward=20
compatibility.
If you don't think this is a good goal to have, you are of course entitled=
=20
to that opinion, but I think you won't find many like-minded people in the=
=20
C++ community, much less the standard committee.
=20
> But with *improvements* (sorry, but everyone seem to miss that this is my=
=20
> point) it could also work in the place of mixins.
>
No, I get it. But the preprocessor is fundamentally, irrevocably at a=20
completely different level than the rest of the language - it has its own=
=20
rules about what a token is! There's just no place to *start* when you=20
suggest improvements to the preprocessor to make it a viable way of=20
routinely doing things.
=20
> Same way as MI / CRTP could.
>
Awaiting your reply to my earlier post.
=20
> Either way, with "small" standard changes you could have what you need=20
> (with different syntax), and the language doesn't need an extra ~hundred=
=20
> pages describing every single current feature's interaction with the new=
=20
> mixin feature.
>
I don't know why you put "small" in quotes. Maybe because you yourself=20
don't believe they are actually small changes? To achieve what I want, you=
=20
would have to mangle the current concept of inheritance beyond recognition,=
=20
and if you do that, what is the point of using inheritance?
=20
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_57_24001336.1377694787741
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, August 28, 2013 2:44:01 PM UTC+2, R=F3bert D=
=E1vid wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><br><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>Macro=
s are a hack. Every use of macros indicates a place where the core language=
is lacking.</div><div><br></div></div></blockquote><div><br>Macros are par=
t of the language. It will not go away. We have to live with this fact.<br>=
</div></div></blockquote><div><br></div><div>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 includ=
es. We cannot ever get rid of the preprocessor, but we want to relegate it =
to exotic uses and backward compatibility.</div><div>If you don't think thi=
s 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 le=
ss the standard committee.</div><div> <br></div><blockquote class=3D"g=
mail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc sol=
id;padding-left: 1ex;"><div dir=3D"ltr"><div>But with <font size=3D"6"><u><=
b>improvements</b></u></font> (sorry, but everyone seem to miss that this i=
s my point) it could also work in the place of mixins.</div></div></blockqu=
ote><div><br></div><div>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 *st=
art* when you suggest improvements to the preprocessor to make it a viable =
way of routinely doing things.</div><div> </div><blockquote class=3D"g=
mail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc sol=
id;padding-left: 1ex;"><div dir=3D"ltr"><div> Same way as MI / CRTP could.<=
/div></div></blockquote><div><br></div><div>Awaiting your reply to my earli=
er post.</div><div> </div><blockquote class=3D"gmail_quote" style=3D"m=
argin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"=
><div dir=3D"ltr"><div> 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 interacti=
on with the new mixin feature.<br></div></div></blockquote><div><br></div><=
div>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?</div><div>&nbs=
p;</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_57_24001336.1377694787741--
.
Author: =?UTF-8?Q?R=C3=B3bert_D=C3=A1vid?= <lrdxgm@gmail.com>
Date: Wed, 28 Aug 2013 06:37:19 -0700 (PDT)
Raw View
------=_Part_46_15052484.1377697039333
Content-Type: text/plain; charset=ISO-8859-2
Content-Transfer-Encoding: quoted-printable
2013. augusztus 28., szerda 14:59:47 UTC+2 id=F5pontban corn...@google.com =
a=20
k=F6vetkez=F5t =EDrta:
>
>
> I don't know why you put "small" in quotes.=20
> =20
>
There is no such thing as a small change in a standard. You cannot just add=
=20
3 lines into the standard text and done, you need to think over what is the=
=20
implication of the change for a compiler author, how does it work well with=
=20
other language features, and add text about how those features work if they=
=20
encounter the new feature. My example of adding a __THIS_CLASS__ magic=20
macro will probably not break much stuff, probably does not have to change=
=20
a lot of other stuff, but I still not sure. I'm absolutely sure about=20
adding the proposed mixin will wreak havoc among in almost every single=20
clause of the language. It will be so complex you will (figuratively) never=
=20
get your feature, while some current feature can be improved to fit, you=20
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=
=20
chance.
Regards, Robert
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_46_15052484.1377697039333
Content-Type: text/html; charset=ISO-8859-2
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>2013. augusztus 28., szerda 14:59:47 UTC+2 id=F5po=
ntban corn...@google.com a k=F6vetkez=F5t =EDrta:<blockquote class=3D"gmail=
_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;p=
adding-left: 1ex;"><div dir=3D"ltr"><br><div>I don't know why you put "smal=
l" in quotes. <br></div><div> </div></div></blockquote><div><br>There =
is no such thing as a small change in a standard. You cannot just add 3 lin=
es into the standard text and done, you need to think over what is the impl=
ication of the change for a compiler author, how does it work well with oth=
er language features, and add text about how those features work if they en=
counter 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 feat=
ure, while some current feature can be improved to fit, you might even get =
it in C++17.<br><br>That's why.<br><br>The CRTP question needs some time to=
answer, I'll get there when I have the chance.<br><br>Regards, Robert<br><=
/div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_46_15052484.1377697039333--
.
Author: Maurice Bos <m-ou.se@m-ou.se>
Date: Wed, 28 Aug 2013 15:46:14 +0200
Raw View
--089e013c6760bade8104e502379c
Content-Type: text/plain; charset=ISO-8859-2
Content-Transfer-Encoding: quoted-printable
__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=F3bert D=E1vid <lrdxgm@gmail.com>
>
>
> 2013. augusztus 28., szerda 14:59:47 UTC+2 id=F5pontban corn...@google.co=
ma k=F6vetkez=F5t =EDrta:
>
>>
>> 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 wel=
l
> 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__ mag=
ic
> macro will probably not break much stuff, probably does not have to chang=
e
> 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) nev=
er
> 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
>
> --
>
> ---
> 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-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--089e013c6760bade8104e502379c
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">__THIS_CLASS__ cannot be a macro, for the same reason __fu=
nc__ 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 p=
reprocessor at all.<br>
</div><div class=3D"gmail_extra"><br><br><div class=3D"gmail_quote">2013/8/=
28 R=C3=B3bert D=C3=A1vid <span dir=3D"ltr"><<a href=3D"mailto:lrdxgm@gm=
ail.com" target=3D"_blank">lrdxgm@gmail.com</a>></span><br><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;=
padding-left:1ex">
<div dir=3D"ltr"><br><br>2013. augusztus 28., szerda 14:59:47 UTC+2 id=C5=
=91pontban <a href=3D"mailto:corn...@google.com" target=3D"_blank">corn...@=
google.com</a> a k=C3=B6vetkez=C5=91t =C3=ADrta:<div class=3D"im"><blockquo=
te class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
<div dir=3D"ltr"><br><div>I don't know why you put "small" in=
quotes. <br></div><div>=C2=A0</div></div></blockquote></div><div><br>There=
is no such thing as a small change in a standard. You cannot just add 3 li=
nes into the standard text and done, you need to think over what is the imp=
lication of the change for a compiler author, how does it work well with ot=
her language features, and add text about how those features work if they e=
ncounter 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.<br>
<br>That's why.<br><br>The CRTP question needs some time to answer, I&#=
39;ll get there when I have the chance.<br><br>Regards, Robert<br></div></d=
iv><div class=3D"HOEnZb"><div class=3D"h5">
<p></p>
-- <br>
=C2=A0<br>
--- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals%2Bunsubscribe@isocpp.org" target=3D=
"_blank">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e013c6760bade8104e502379c--
.
Author: cornedbee@google.com
Date: Wed, 28 Aug 2013 06:55:13 -0700 (PDT)
Raw View
------=_Part_26_2706753.1377698113606
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On Wednesday, August 28, 2013 3:37:19 PM UTC+2, R=F3bert D=E1vid wrote:
>
>
> I'm absolutely sure about adding the proposed mixin will wreak havoc amon=
g=20
> in almost every single clause of the language. It will be so complex you=
=20
> will (figuratively) never get your feature,
>
I am quite familiar with reading and implementing the standard. I disagree=
=20
with your assessment. The feature is pretty well isolated for such a big=20
thing. The most intrusive change is the issue of completeness of the=20
embedding class when instantiating the mixin, and the lookup rules will be=
=20
affected by the injected names depending on the exact resolution of the=20
pending issues there, but that's not unexpected.
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_26_2706753.1377698113606
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Wednesday, August 28, 2013 3:37:19 PM UTC+2, R=
=F3bert D=E1vid wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><br>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 c=
omplex you will (figuratively) never get your feature,</div></blockquote><d=
iv><br></div><div>I am quite familiar with reading and implementing the sta=
ndard. I disagree with your assessment. The feature is pretty well isolated=
for such a big thing. The most intrusive change is the issue of completene=
ss of the embedding class when instantiating the mixin, and the lookup rule=
s will be affected by the injected names depending on the exact resolution =
of the pending issues there, but that's not unexpected.</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_26_2706753.1377698113606--
.
Author: =?ISO-8859-1?B?ROF2aWQgUvNiZXJ0?= <lrdxgm@gmail.com>
Date: Thu, 29 Aug 2013 03:11:47 +0200
Raw View
--047d7b5d9c6b43ac1f04e50bca3b
Content-Type: text/plain; charset=ISO-8859-1
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
--
---
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--047d7b5d9c6b43ac1f04e50bca3b
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">How should mixins behave with inheritance, is it "inh=
eriting" the mixin=20
(so if descendants are also "using" it), or is ends there, descen=
dants=20
just get the members like they were defined normally?<br><br>Consider:<br><=
div class=3D"" style=3D"background-color:rgb(250,250,250);border-color:rgb(=
187,187,187);border-style:solid;border-width:1px;word-wrap:break-word"><cod=
e class=3D""><div class=3D"">
<span style=3D"color:rgb(0,0,0)" class=3D"">mixin cloneable </span><span st=
yle=3D"color:rgb(102,102,0)" class=3D"">{</span><span style=3D"color:rgb(0,=
0,0)" class=3D""><br>=A0 cloneable</span><span style=3D"color:rgb(102,102,0=
)" class=3D"">*</span><span style=3D"color:rgb(0,0,0)" class=3D""> clone</s=
pan><span style=3D"color:rgb(102,102,0)" class=3D"">()</span><span style=3D=
"color:rgb(0,0,0)" class=3D""> </span><span style=3D"color:rgb(0,0,136)" cl=
ass=3D"">const</span><span style=3D"color:rgb(0,0,0)" class=3D""> </span><s=
pan style=3D"color:rgb(102,102,0)" class=3D"">{</span><span style=3D"color:=
rgb(0,0,0)" class=3D""> </span><span style=3D"color:rgb(0,0,136)" class=3D"=
">return</span><span style=3D"color:rgb(0,0,0)" class=3D""> </span><span st=
yle=3D"color:rgb(0,0,136)" class=3D"">new</span><span style=3D"color:rgb(0,=
0,0)" class=3D""> cloneable</span><span style=3D"color:rgb(102,102,0)" clas=
s=3D"">;</span><span style=3D"color:rgb(0,0,0)" class=3D""> </span><span st=
yle=3D"color:rgb(102,102,0)" class=3D"">}</span><span style=3D"color:rgb(0,=
0,0)" class=3D""><br>
</span><span style=3D"color:rgb(102,102,0)" class=3D"">};</span><span style=
=3D"color:rgb(0,0,0)" class=3D""><br></span><span style=3D"color:rgb(0,0,13=
6)" class=3D"">struct</span><span style=3D"color:rgb(0,0,0)" class=3D""> </=
span><span style=3D"color:rgb(102,0,102)" class=3D"">Foo</span><span style=
=3D"color:rgb(0,0,0)" class=3D""> </span><span style=3D"color:rgb(102,102,0=
)" class=3D"">{</span><span style=3D"color:rgb(0,0,0)" class=3D""><br>
=A0 </span><span style=3D"color:rgb(0,0,136)" class=3D"">using</span><span =
style=3D"color:rgb(0,0,0)" class=3D""> mixin cloneable</span><span style=3D=
"color:rgb(102,102,0)" class=3D"">;</span><span style=3D"color:rgb(0,0,0)" =
class=3D""><br>
</span><span style=3D"color:rgb(102,102,0)" class=3D"">};</span><span style=
=3D"color:rgb(0,0,0)" class=3D""><br></span><span style=3D"color:rgb(0,0,13=
6)" class=3D"">struct</span><span style=3D"color:rgb(0,0,0)" class=3D""> </=
span><span style=3D"color:rgb(102,0,102)" class=3D"">Bar</span><span style=
=3D"color:rgb(0,0,0)" class=3D""> </span><span style=3D"color:rgb(102,102,0=
)" class=3D"">:</span><span style=3D"color:rgb(0,0,0)" class=3D""> </span><=
span style=3D"color:rgb(0,0,136)" class=3D"">public</span><span style=3D"co=
lor:rgb(0,0,0)" class=3D""> </span><span style=3D"color:rgb(102,0,102)" cla=
ss=3D"">Foo</span><span style=3D"color:rgb(0,0,0)" class=3D""> </span><span=
style=3D"color:rgb(102,102,0)" class=3D"">{</span><span style=3D"color:rgb=
(0,0,0)" class=3D""><br>
</span><span style=3D"color:rgb(102,102,0)" class=3D"">};</span><span style=
=3D"color:rgb(0,0,0)" class=3D""><br><br></span><span style=3D"color:rgb(0,=
0,136)" class=3D"">using</span><span style=3D"color:rgb(0,0,0)" class=3D"">=
A </span><span style=3D"color:rgb(102,102,0)" class=3D"">=3D</span><span s=
tyle=3D"color:rgb(0,0,0)" class=3D""> </span><span style=3D"color:rgb(0,0,1=
36)" class=3D"">decltype</span><span style=3D"color:rgb(102,102,0)" class=
=3D"">(</span><span style=3D"color:rgb(102,0,102)" class=3D"">Bar</span><sp=
an style=3D"color:rgb(102,102,0)" class=3D"">().</span><span style=3D"color=
:rgb(0,0,0)" class=3D"">clone</span><span style=3D"color:rgb(102,102,0)" cl=
ass=3D"">());</span><span style=3D"color:rgb(0,0,0)" class=3D""><br>
</span></div></code></div>Is type A equal to Foo* or Bar*? Is Bar cloneable=
?<br><br>Consider:<br><div class=3D"" style=3D"background-color:rgb(250,250=
,250);border-color:rgb(187,187,187);border-style:solid;border-width:1px;wor=
d-wrap:break-word">
<code class=3D""><div class=3D""><span style=3D"color:rgb(0,0,0)" class=3D"=
">mixin noncopyable </span><span style=3D"color:rgb(102,102,0)" class=3D"">=
{</span><span style=3D"color:rgb(0,0,0)" class=3D""><br>=A0 noncopyable</sp=
an><span style=3D"color:rgb(102,102,0)" class=3D"">(</span><span style=3D"c=
olor:rgb(0,0,136)" class=3D"">const</span><span style=3D"color:rgb(0,0,0)" =
class=3D""> noncopyable</span><span style=3D"color:rgb(102,102,0)" class=3D=
"">&)</span><span style=3D"color:rgb(0,0,0)" class=3D""> </span><span s=
tyle=3D"color:rgb(102,102,0)" class=3D"">=3D</span><span style=3D"color:rgb=
(0,0,0)" class=3D""> </span><span style=3D"color:rgb(0,0,136)" class=3D"">d=
elete</span><span style=3D"color:rgb(102,102,0)" class=3D"">;</span><span s=
tyle=3D"color:rgb(0,0,0)" class=3D""><br>
</span><span style=3D"color:rgb(102,102,0)" class=3D"">};</span><span style=
=3D"color:rgb(0,0,0)" class=3D""><br></span><span style=3D"color:rgb(0,0,13=
6)" class=3D"">struct</span><span style=3D"color:rgb(0,0,0)" class=3D""> </=
span><span style=3D"color:rgb(102,0,102)" class=3D"">Foo</span><span style=
=3D"color:rgb(102,102,0)" class=3D"">{</span><span style=3D"color:rgb(0,0,0=
)" class=3D""><br>
=A0 </span><span style=3D"color:rgb(0,0,136)" class=3D"">using</span><span =
style=3D"color:rgb(0,0,0)" class=3D""> mixin noncopyable</span><span style=
=3D"color:rgb(102,102,0)" class=3D"">;</span><span style=3D"color:rgb(0,0,0=
)" class=3D""><br>
</span><span style=3D"color:rgb(102,102,0)" class=3D"">};</span><span style=
=3D"color:rgb(0,0,0)" class=3D""><br></span><code class=3D""><span style=3D=
"color:rgb(0,0,136)" class=3D"">struct</span><span style=3D"color:rgb(0,0,0=
)" class=3D""> </span><span style=3D"color:rgb(102,0,102)" class=3D""></spa=
n></code><span style=3D"color:rgb(102,0,102)" class=3D"">Bar</span><span st=
yle=3D"color:rgb(0,0,0)" class=3D""> </span><span style=3D"color:rgb(102,10=
2,0)" class=3D"">:</span><span style=3D"color:rgb(0,0,0)" class=3D""> </spa=
n><span style=3D"color:rgb(0,0,136)" class=3D"">public</span><span style=3D=
"color:rgb(0,0,0)" class=3D""> Foo {<br>
=A0 Bar(const Bar&) : Foo() {}<br>}<br></span></div></code></div>Is Bar=
noncopyable (conflicting with the copy constructor definition, making Bar =
ill-formed)?<br><br>Regards, Robert</div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7b5d9c6b43ac1f04e50bca3b--
.
Author: cornedbee@google.com
Date: Thu, 29 Aug 2013 02:38:11 -0700 (PDT)
Raw View
------=_Part_742_33182845.1377769091626
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On Thursday, August 29, 2013 3:11:47 AM UTC+2, R=F3bert D=E1vid wrote:
>
> How should mixins behave with inheritance, is it "inheriting" the mixin=
=20
> (so if descendants are also "using" it), or is ends there, descendants ju=
st=20
> get the members like they were defined normally?
>
They just get the members. Anything else would be extremely confusing.
=20
>
> Consider:
> mixin cloneable {
> cloneable* clone() const { return new cloneable; }
> };
> struct Foo {
> using mixin cloneable;
> };
> struct Bar : public Foo {
> };
>
> using A =3D 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=20
"cloneable" in the sense that you can call clone() on it, but it will do=20
the wrong thing.
=20
>
> Consider:
> mixin noncopyable {
> noncopyable(const noncopyable&) =3D delete;
> };
> struct Foo{
> using mixin noncopyable;
> };
> struct Bar : public Foo {
> Bar(const Bar&) : Foo() {}
> }
> Is Bar noncopyable (conflicting with the copy constructor definition,=20
> making Bar ill-formed)?
>
>
Bar is well-formed and copyable.
=20
Sebastian
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_742_33182845.1377769091626
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Thursday, August 29, 2013 3:11:47 AM UTC+2, R=
=F3bert D=E1vid wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr">How should mixins behave with inheritance, is it "inheriting" the =
mixin=20
(so if descendants are also "using" it), or is ends there, descendants=20
just get the members like they were defined normally?<br></div></blockquote=
><div><br></div><div>They just get the members. Anything else would be extr=
emely confusing.</div><div> </div><blockquote class=3D"gmail_quote" st=
yle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-lef=
t: 1ex;"><div dir=3D"ltr"><br>Consider:<br><div style=3D"background-color:r=
gb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-wid=
th:1px;word-wrap:break-word"><code><div>
<span style=3D"color:rgb(0,0,0)">mixin cloneable </span><span style=3D"colo=
r:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,0,0)"><br> clone=
able</span><span style=3D"color:rgb(102,102,0)">*</span><span style=3D"colo=
r:rgb(0,0,0)"> clone</span><span style=3D"color:rgb(102,102,0)">()</span><s=
pan style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">c=
onst</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rg=
b(102,102,0)">{</span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(0,0,136)">return</span><span style=3D"color:rgb(0,0,0)"> </sp=
an><span style=3D"color:rgb(0,0,136)">new</span><span style=3D"color:rgb(0,=
0,0)"> cloneable</span><span style=3D"color:rgb(102,102,0)">;</span><span s=
tyle=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">}</s=
pan><span style=3D"color:rgb(0,0,0)"><br>
</span><span style=3D"color:rgb(102,102,0)">};</span><span style=3D"color:r=
gb(0,0,0)"><br></span><span style=3D"color:rgb(0,0,136)">struct</span><span=
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">Fo=
o</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(1=
02,102,0)">{</span><span style=3D"color:rgb(0,0,0)"><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D=
"color:rgb(0,0,0)"> mixin cloneable</span><span style=3D"color:rgb(102,102,=
0)">;</span><span style=3D"color:rgb(0,0,0)"><br>
</span><span style=3D"color:rgb(102,102,0)">};</span><span style=3D"color:r=
gb(0,0,0)"><br></span><span style=3D"color:rgb(0,0,136)">struct</span><span=
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">Ba=
r</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(1=
02,102,0)">:</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"=
color:rgb(0,0,136)">public</span><span style=3D"color:rgb(0,0,0)"> </span><=
span style=3D"color:rgb(102,0,102)">Foo</span><span style=3D"color:rgb(0,0,=
0)"> </span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"col=
or:rgb(0,0,0)"><br>
</span><span style=3D"color:rgb(102,102,0)">};</span><span style=3D"color:r=
gb(0,0,0)"><br><br></span><span style=3D"color:rgb(0,0,136)">using</span><s=
pan style=3D"color:rgb(0,0,0)"> A </span><span style=3D"color:rgb(102,102,0=
)">=3D</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:=
rgb(0,0,136)">decltype</span><span style=3D"color:rgb(102,102,0)">(</span><=
span style=3D"color:rgb(102,0,102)">Bar</span><span style=3D"color:rgb(102,=
102,0)">().</span><span style=3D"color:rgb(0,0,0)">clone</span><span style=
=3D"color:rgb(102,102,0)">());</span><span style=3D"color:rgb(0,0,0)"><br>
</span></div></code></div>Is type A equal to Foo* or Bar*? Is Bar cloneable=
?<br></div></blockquote><div><br></div><div>Bar does not have its own overr=
ide of clone(). A is Foo*. Bar is still "cloneable" in the sense that you c=
an call clone() on it, but it will do the wrong thing.</div><div> </di=
v><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><br>Conside=
r:<br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,=
187,187);border-style:solid;border-width:1px;word-wrap:break-word">
<code><div><span style=3D"color:rgb(0,0,0)">mixin noncopyable </span><span =
style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,0,0)"><br=
> noncopyable</span><span style=3D"color:rgb(102,102,0)">(</span><spa=
n style=3D"color:rgb(0,0,136)">const</span><span style=3D"color:rgb(0,0,0)"=
> noncopyable</span><span style=3D"color:rgb(102,102,0)">&)</span><span=
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">=
=3D</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb=
(0,0,136)">delete</span><span style=3D"color:rgb(102,102,0)">;</span><span =
style=3D"color:rgb(0,0,0)"><br>
</span><span style=3D"color:rgb(102,102,0)">};</span><span style=3D"color:r=
gb(0,0,0)"><br></span><span style=3D"color:rgb(0,0,136)">struct</span><span=
style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">Fo=
o</span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:r=
gb(0,0,0)"><br>
</span><span style=3D"color:rgb(0,0,136)">using</span><span style=3D=
"color:rgb(0,0,0)"> mixin noncopyable</span><span style=3D"color:rgb(102,10=
2,0)">;</span><span style=3D"color:rgb(0,0,0)"><br>
</span><span style=3D"color:rgb(102,102,0)">};</span><span style=3D"color:r=
gb(0,0,0)"><br></span><code><span style=3D"color:rgb(0,0,136)">struct</span=
><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,10=
2)"></span></code><span style=3D"color:rgb(102,0,102)">Bar</span><span styl=
e=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">:</span=
><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)=
">public</span><span style=3D"color:rgb(0,0,0)"> Foo {<br>
Bar(const Bar&) : Foo() {}<br>}<br></span></div></code></div>Is =
Bar noncopyable (conflicting with the copy constructor definition, making B=
ar ill-formed)?<br><br></div></blockquote><div><br></div><div>Bar is well-f=
ormed and copyable.</div><div> </div><div>Sebastian</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_742_33182845.1377769091626--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Thu, 29 Aug 2013 19:25:27 -0400
Raw View
--001a1133aa86d9a12d04e51e6bf5
Content-Type: text/plain; charset=ISO-8859-1
On Tue, Aug 27, 2013 at 5:14 PM, Sebastian Redl <wasti.redl@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
--
---
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1133aa86d9a12d04e51e6bf5
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><br><div class=3D"gmail=
_quote">On Tue, Aug 27, 2013 at 5:14 PM, Sebastian Redl <span dir=3D"ltr">&=
lt;<a href=3D"mailto:wasti.redl@gmx.net" target=3D"_blank">wasti.redl@gmx.n=
et</a>></span> wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div dir=3D"ltr"><br><br>=3D=3D=3D Mixins (C=
lass Extension Blocks) for C++ =3D=3D=3D<br><br><br><span style=3D"font-fam=
ily:courier new,monospace"></span><br>
</div></blockquote></div><br><br></div><div class=3D"gmail_extra">The idea =
of making it easier to implement > in terms of <, etc comes up often =
in the Committee.=A0 ie operator>() =3D default;=A0 (or some other synta=
x).=A0 I suspect it will eventually happen.=A0 Bjarne seems interested (IMO=
at least).<br>
<br></div><div class=3D"gmail_extra">That would be nice, but you might stil=
l need to do that for each operator.=A0 I'd prefer one line "mixin=
std::operators;" or something like that.<br><br></div><div class=3D"g=
mail_extra">
I think a nice general mixin solution would be better than trying to solve =
all the little cases.<br><br></div><div class=3D"gmail_extra">Tony<br></div=
></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1133aa86d9a12d04e51e6bf5--
.
Author: stackmachine@hotmail.com
Date: Thu, 29 Aug 2013 17:59:59 -0700 (PDT)
Raw View
------=_Part_159_29370498.1377824399570
Content-Type: text/plain; charset=ISO-8859-1
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.
--
---
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_159_29370498.1377824399570
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I very much like this idea. Two things:<br><ul><li>There h=
as been at least a thread to propose decltype(class) to mean "the type of t=
he current class". This is what __THIS_CLASS__ is supposed to be, with a ni=
ce syntax imo.</li><li>I've had an idea in my head for a long time that see=
ms to be much more flexible than yours. I call it "code generators". <br>Th=
e best way to explain this feature is probably using an example.</li></ul><=
p><code></code></p><div class=3D"prettyprint" style=3D"background-color: rg=
b(250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; bo=
rder-width: 1px; word-wrap: break-word;"><code><code class=3D"prettyprint">=
<div class=3D"subprettyprint"><span style=3D"color: #000;" class=3D"styled-=
by-prettify">codegen noncopyable</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">()</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br> emit<br></span><code><code class=3D"prettyprint"><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> {</span></=
code></code><br><code><code class=3D"prettyprint"><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span></code></code><code><=
code class=3D"prettyprint"><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> decltype(class)(decltype(class) const&) =3D del=
ete;<br></span></code></code><code><code class=3D"prettyprint"><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span></code>=
</code><code><code class=3D"prettyprint"><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> decltype(class)& operator =3D (de=
cltype(class) const&) =3D delete;</span></code></code><br><code><code c=
lass=3D"prettyprint"><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> }</span></code></code><br><code><code class=3D"prettyprin=
t"><span style=3D"color: #000;" class=3D"styled-by-prettify"></span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"></span></code></code><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span></div></code></co=
de></div><code>This thing is not just a macro with better syntax, it is a f=
ully-fledged constexpr function that can have compiletime-loops and use com=
piletime reflection to generate code. The only difference to a regular cons=
texpr function is that it does not have a return type and instead emits cod=
e.</code><p></p><p><code>Let's see how this can be used:</code></p><p><code=
></code></p><div class=3D"prettyprint" style=3D"background-color: rgb(250, =
250, 250); border-color: rgb(187, 187, 187); border-style: solid; border-wi=
dth: 1px; word-wrap: break-word;"><code><code class=3D"prettyprint"><div cl=
ass=3D"subprettyprint"><span style=3D"color: #606;" class=3D"styled-by-pret=
tify">struct Foo<br>{<br></span><code><code class=3D"prettyprint"><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span></cod=
e></code>$noncopyable() // special call syntax could be using the $-sign or=
some other currently unused character<br><span style=3D"color: #606;" clas=
s=3D"styled-by-prettify"><code><code class=3D"prettyprint"><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"></span></code></code>};<br></span=
><span style=3D"color: #660;" class=3D"styled-by-prettify"></span></div></c=
ode></code></div><code>Another idea I had is a special "operator emit"</cod=
e><code> that can be overloaded by classes to allow us to carry code around=
statefully. I have not yet put enough thought into this though.</code><br>=
<code></code><br><br><p></p></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_159_29370498.1377824399570--
.
Author: David Krauss <potswa@gmail.com>
Date: Thu, 29 Aug 2013 23:19:57 -0700 (PDT)
Raw View
------=_Part_332_2399213.1377843597595
Content-Type: text/plain; charset=ISO-8859-1
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 initializeand
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!)
--
---
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_332_2399213.1377843597595
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br>On Wednesday, August 28, 2013 8:07:11 PM UTC+8, corn..=
..@google.com wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin: 0=
;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div di=
r=3D"ltr"><br>On Wednesday, August 28, 2013 1:21:09 PM UTC+2, David Krauss =
wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0=
..8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">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-initial=
izer.<br></div></blockquote><div><br></div><div>It's not a using declaratio=
n. It's a using mixin directive. ;-)</div></div></blockquote><blockquote st=
yle=3D"margin: 0px 0px 0px 0.8ex; border-left: 1px solid rgb(204, 204, 204)=
; padding-left: 1ex;" class=3D"gmail_quote"><div> </div></blockquote><=
blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bord=
er-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>Yes, mixi=
ns can have constructors and destructors so that they can maintain their ow=
n invariants. And yes, I fully intend them to be called from the initialize=
r list of the embedding class, using the mixin's name, mingled with the mem=
ber variables of the class. I don't see why that's unintuitive, and especia=
lly not how new syntax would be any better.</div></div></blockquote><div><b=
r>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 constru=
ctor from its body. The same actually goes for destructors: the host destru=
ctor needs to relinquish the mixin at some point in its execution, not befo=
re beginning or after ending.<br><br>Maybe I'm making something out of noth=
ing. There can always be <span style=3D"font-family: courier new,monospace;=
">initialize</span> and <span style=3D"font-family: courier new,monospace;"=
>finalize</span> methods in addition to the constructor and destructor. Mov=
ing the calls of the constructor and destructor would wreak havoc with obje=
ct lifetimes.<br><br>On the other hand, being able to defer initialization =
of a member whose constructor arguments require more preparation than can b=
e accomplished in the mem-initializer-list would work around a longstanding=
issue. All we really need after all is to make UB use before initializatio=
n.<br> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"=
ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;=
border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">Recently I su=
ggested 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 re=
ally 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.<br></div><=
/blockquote><div> </div><div>Using concepts on the parameter of a CRTP=
base - interesting idea. I'm not sure how concept checks would work for in=
complete types, though.</div></div></blockquote><div><br>Concepts are appli=
cable to any template parameter, and tolerating an incomplete argument is g=
enerally considered to be a good thing. There should be a modifier, applica=
ble to any concept parameter declaration, that defers the check until an in=
complete class type is completed. (I just figured this out now, should star=
t a new thread. Thanks for the impetus!)<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_332_2399213.1377843597595--
.
Author: cornedbee@google.com
Date: Fri, 30 Aug 2013 05:55:29 -0700 (PDT)
Raw View
------=_Part_41_27012609.1377867329902
Content-Type: text/plain; charset=ISO-8859-1
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 initializeand
> 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.
--
---
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_41_27012609.1377867329902
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Friday, August 30, 2013 8:19:57 AM UTC+2, David=
Krauss wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"=
><br>On Wednesday, August 28, 2013 8:07:11 PM UTC+8, <a>corn...@google.com<=
/a> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-le=
ft:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">&nbs=
p;<br></div></blockquote><blockquote class=3D"gmail_quote" style=3D"margin:=
0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr"><div>Yes, mixins can have constructors and destructors so that the=
y can maintain their own invariants. And yes, I fully intend them to be cal=
led from the initializer list of the embedding class, using the mixin's nam=
e, mingled with the member variables of the class. I don't see why that's u=
nintuitive, and especially not how new syntax would be any better.</div></d=
iv></blockquote><div><br>Often the invariants for members are not establish=
ed by the first line of the constructor body. A mixin depending on some fun=
ctionality in the host class would expect invariants for the host members i=
ts constructor accesses.</div></div></blockquote><div><br></div><div>This i=
s a good point, but I think it is the exception rather than the rule.</div>=
<div> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div> 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 hos=
t destructor needs to relinquish the mixin at some point in its execution, =
not before beginning or after ending.<br><br>Maybe I'm making something out=
of nothing. There can always be <span style=3D"font-family:courier new,mon=
ospace">initialize</span> and <span style=3D"font-family:courier new,monosp=
ace">finalize</span> methods in addition to the constructor and destructor.=
Moving the calls of the constructor and destructor would wreak havoc with =
object lifetimes.<br></div></div></blockquote><div><br></div><div>I have no=
idea how common this situation would be. My gut feeling says "very uncommo=
n, initialize and finalize are fine as workarounds", but I don't know how m=
uch of that is wishful thinking.</div><div> </div><blockquote class=3D=
"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc s=
olid;padding-left: 1ex;"><div dir=3D"ltr"><div><br>On the other hand, being=
able to defer initialization of a member whose constructor arguments requi=
re more preparation than can be accomplished in the mem-initializer-list wo=
uld work around a longstanding issue. All we really need after all is to ma=
ke UB use before initialization.<br></div></div></blockquote><div><br></div=
><div>No, that's not all. Consider:</div><div><br></div><div>class A {</div=
><div> B b;</div><div> C c;</div><div>public:</div><div> =
A(int x, int y)</div><div> : b(defer), // let's make this expl=
icit</div><div> c(x) // could throw</div><div> {<=
/div><div> int z =3D foobar(x); // could also throw</div><div>=
b.B(y, z);</div><div> c.froblize(b); // could al=
so throw</div><div> }</div><div>};</div><div><br></div><div>Keeping t=
he order of destruction correct in the face of such a feature would be non-=
trivial.</div><div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_41_27012609.1377867329902--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Sat, 31 Aug 2013 08:59:19 +0200
Raw View
This is a multi-part message in MIME format.
--------------080803040909030602030005
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 29/08/13 11:38, cornedbee@google.com a =E9crit :
>
>
> On Thursday, August 29, 2013 3:11:47 AM UTC+2, R=F3bert D=E1vid 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=20
approach, as cloneable must be repeated for each derived class.
>
>
> Consider:
> |
> mixin cloneable {
> cloneable*clone()const{returnnewcloneable;}
> };
> structFoo{
> usingmixin cloneable;
> };
> structBar:publicFoo{
> };
>
> usingA =3Ddecltype(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=20
> "cloneable" in the sense that you can call clone() on it, but it will=20
> do the wrong thing.
Note that the same occurs if mixins are implemented using CRTP.
>
>
> Consider:
> |
> mixin noncopyable {
> noncopyable(constnoncopyable&)=3Ddelete;
> };
> structFoo{
> usingmixin noncopyable;
> };
> |struct|Bar:publicFoo {
> 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
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------080803040909030602030005
Content-Type: text/html; charset=ISO-8859-1
<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div class="moz-cite-prefix">Le 29/08/13 11:38, <a class="moz-txt-link-abbreviated" href="mailto:cornedbee@google.com">cornedbee@google.com</a>
a écrit :<br>
</div>
<blockquote
cite="mid:1ff4e759-ddf8-481a-ae5d-33f492e4665d@isocpp.org"
type="cite">
<div dir="ltr"><br>
<br>
On Thursday, August 29, 2013 3:11:47 AM UTC+2, Róbert Dávid
wrote:
<blockquote class="gmail_quote" style="margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div dir="ltr">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?<br>
</div>
</blockquote>
<div><br>
</div>
<div>They just get the members. Anything else would be extremely
confusing.</div>
</div>
</blockquote>
I agree, even if for the example below it would be an interesting
approach, as cloneable must be repeated for each derived class. <br>
<blockquote
cite="mid:1ff4e759-ddf8-481a-ae5d-33f492e4665d@isocpp.org"
type="cite">
<div dir="ltr">
<div> </div>
<blockquote class="gmail_quote" style="margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div dir="ltr"><br>
Consider:<br>
<div
style="background-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:break-word"><code>
<div>
<span style="color:rgb(0,0,0)">mixin cloneable </span><span
style="color:rgb(102,102,0)">{</span><span
style="color:rgb(0,0,0)"><br>
cloneable</span><span style="color:rgb(102,102,0)">*</span><span
style="color:rgb(0,0,0)"> clone</span><span
style="color:rgb(102,102,0)">()</span><span
style="color:rgb(0,0,0)"> </span><span
style="color:rgb(0,0,136)">const</span><span
style="color:rgb(0,0,0)"> </span><span
style="color:rgb(102,102,0)">{</span><span
style="color:rgb(0,0,0)"> </span><span
style="color:rgb(0,0,136)">return</span><span
style="color:rgb(0,0,0)"> </span><span
style="color:rgb(0,0,136)">new</span><span
style="color:rgb(0,0,0)"> cloneable</span><span
style="color:rgb(102,102,0)">;</span><span
style="color:rgb(0,0,0)"> </span><span
style="color:rgb(102,102,0)">}</span><span
style="color:rgb(0,0,0)"><br>
</span><span style="color:rgb(102,102,0)">};</span><span
style="color:rgb(0,0,0)"><br>
</span><span style="color:rgb(0,0,136)">struct</span><span
style="color:rgb(0,0,0)"> </span><span
style="color:rgb(102,0,102)">Foo</span><span
style="color:rgb(0,0,0)"> </span><span
style="color:rgb(102,102,0)">{</span><span
style="color:rgb(0,0,0)"><br>
</span><span style="color:rgb(0,0,136)">using</span><span
style="color:rgb(0,0,0)"> mixin cloneable</span><span
style="color:rgb(102,102,0)">;</span><span
style="color:rgb(0,0,0)"><br>
</span><span style="color:rgb(102,102,0)">};</span><span
style="color:rgb(0,0,0)"><br>
</span><span style="color:rgb(0,0,136)">struct</span><span
style="color:rgb(0,0,0)"> </span><span
style="color:rgb(102,0,102)">Bar</span><span
style="color:rgb(0,0,0)"> </span><span
style="color:rgb(102,102,0)">:</span><span
style="color:rgb(0,0,0)"> </span><span
style="color:rgb(0,0,136)">public</span><span
style="color:rgb(0,0,0)"> </span><span
style="color:rgb(102,0,102)">Foo</span><span
style="color:rgb(0,0,0)"> </span><span
style="color:rgb(102,102,0)">{</span><span
style="color:rgb(0,0,0)"><br>
</span><span style="color:rgb(102,102,0)">};</span><span
style="color:rgb(0,0,0)"><br>
<br>
</span><span style="color:rgb(0,0,136)">using</span><span
style="color:rgb(0,0,0)"> A </span><span
style="color:rgb(102,102,0)">=</span><span
style="color:rgb(0,0,0)"> </span><span
style="color:rgb(0,0,136)">decltype</span><span
style="color:rgb(102,102,0)">(</span><span
style="color:rgb(102,0,102)">Bar</span><span
style="color:rgb(102,102,0)">().</span><span
style="color:rgb(0,0,0)">clone</span><span
style="color:rgb(102,102,0)">());</span><span
style="color:rgb(0,0,0)"><br>
</span></div>
</code></div>
Is type A equal to Foo* or Bar*? Is Bar cloneable?<br>
</div>
</blockquote>
<div><br>
</div>
<div>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.</div>
</div>
</blockquote>
Note that the same occurs if mixins are implemented using CRTP.<br>
<blockquote
cite="mid:1ff4e759-ddf8-481a-ae5d-33f492e4665d@isocpp.org"
type="cite">
<div dir="ltr">
<div> </div>
<blockquote class="gmail_quote" style="margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div dir="ltr"><br>
Consider:<br>
<div
style="background-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:break-word"><code>
<div><span style="color:rgb(0,0,0)">mixin noncopyable </span><span
style="color:rgb(102,102,0)">{</span><span
style="color:rgb(0,0,0)"><br>
noncopyable</span><span
style="color:rgb(102,102,0)">(</span><span
style="color:rgb(0,0,136)">const</span><span
style="color:rgb(0,0,0)"> noncopyable</span><span
style="color:rgb(102,102,0)">&)</span><span
style="color:rgb(0,0,0)"> </span><span
style="color:rgb(102,102,0)">=</span><span
style="color:rgb(0,0,0)"> </span><span
style="color:rgb(0,0,136)">delete</span><span
style="color:rgb(102,102,0)">;</span><span
style="color:rgb(0,0,0)"><br>
</span><span style="color:rgb(102,102,0)">};</span><span
style="color:rgb(0,0,0)"><br>
</span><span style="color:rgb(0,0,136)">struct</span><span
style="color:rgb(0,0,0)"> </span><span
style="color:rgb(102,0,102)">Foo</span><span
style="color:rgb(102,102,0)">{</span><span
style="color:rgb(0,0,0)"><br>
</span><span style="color:rgb(0,0,136)">using</span><span
style="color:rgb(0,0,0)"> mixin noncopyable</span><span
style="color:rgb(102,102,0)">;</span><span
style="color:rgb(0,0,0)"><br>
</span><span style="color:rgb(102,102,0)">};</span><span
style="color:rgb(0,0,0)"><br>
</span><code><span style="color:rgb(0,0,136)">struct</span><span
style="color:rgb(0,0,0)"> </span><span
style="color:rgb(102,0,102)"></span></code><span
style="color:rgb(102,0,102)">Bar</span><span
style="color:rgb(0,0,0)"> </span><span
style="color:rgb(102,102,0)">:</span><span
style="color:rgb(0,0,0)"> </span><span
style="color:rgb(0,0,136)">public</span><span
style="color:rgb(0,0,0)"> Foo {<br>
Bar(const Bar&) : Foo() {}<br>
}<br>
</span></div>
</code></div>
Is Bar noncopyable (conflicting with the copy constructor
definition, making Bar ill-formed)?<br>
<br>
</div>
</blockquote>
<div><br>
</div>
<div>Bar is well-formed and copyable.</div>
<br>
</div>
</blockquote>
This seems counter intuitive. If Foo is not copyable, Bar canot be
copyable.<br>
<br>
Best,<br>
Vicente<br>
<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/</a>.<br />
--------------080803040909030602030005--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Sat, 31 Aug 2013 09:50:25 +0200
Raw View
This is a multi-part message in MIME format.
--------------000101060707090609000507
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 27/08/13 23:14, Sebastian Redl a =E9crit :
> The ability to inject additional code into a class is something that I=20
> have repeatedly missed. Aside from a number of minor uses, I've twice=20
> found myself writing a library that would really have benefited from=20
> such a feature.
>
> Since someone mentioned this feature a few days back, I thought I'd=20
> write up my thoughts on the matter and post them here to gauge=20
> interest and gather comments. Preliminary proposal below.
>
>
> =3D=3D=3D Mixins (Class Extension Blocks) for C++ =3D=3D=3D
>
> --- Purpose ---
> Create a solution for injecting repetitive code into classes that has=20
> 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.=20
> 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=20
not against not for your proposal. I would like just have more insight=20
on the design rationale and why not try to help you to make a better=20
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() !=3D nullptr; }
> bool operator !() const { return get() =3D=3D nullptr; }
> };
>
> Again, one could define a macro to encapsulate these operations, or a bas=
e
> class. However, the base class solution has the problem that it needs=20
> to access
> the get() function in the derived class. There are two possible ways=20
> 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=20
> 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 -=20
> 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=20
> example
> instead of determined by examining Derived (e.g. to look at a nested=20
> 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=20
> 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=20
> either be
> public, or there must be some friendship between the classes.=20
> Specifying the
> entire base class in a friend declaration can be annoying, and=20
> friending a
> type alias wasn't possible before C++11, which led to workarounds=20
> such as
> iterator_core_access (from Boost.Iterator).
>
I have used an alternative approach for mixins. A mixin is a=20
metafunction having a Derived and a Base class. There is a base mixin=20
that defines the self function and that has no Base parameter on the=20
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=20
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**<>*,=20
smart_ptr_mixin<T> >
{
public:
T* get() const { return raw; }
// ...
};
mixins has as parameter the current class, and the list of mixins=20
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=20
> class, but
> is not a type by itself. Instead, a mixin is embedded in (mixed into)=20
> a class;
> its members become members of the class. A mixin is implicitly=20
> templated on the
> type that embeds it, but can in addition have further template=20
> 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&) =3D delete;
> noncopyable& operator =3D(const noncopyable&) =3D delete;
> }
> class foo {
> using mixin noncopyable;
> };
>
> Here, the compiler will fail to generate the copy functions for foo,=20
> because
> they would have to call the mixin's copy functions, which are deleted.=20
> The mixin
> acts like a data member here, including the order of construction=20
> (i.e. when
> data members and mixins are mixed, the constructors are called in the=20
> order of
> declaration).
>
Does making mixins act like data member makes then increase the size of=20
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,=20
> e.g. when
> // we want to use SFINAE tricks on some overloads.
> auto operator *() const -> decltype(*this->get()) { return=20
> *this->get(); }
> auto operator ->() const -> decltype(this->get()) { return=20
> this->get(); }
> explicit operator bool() const { return this->get() !=3D nullptr; }
> bool operator !() const { return this->get() =3D=3D 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=20
> class from
> the mixin.
> Since the mixin is a template, the type of its 'this' pointer is=20
> dependent.
> The syntax for acessing members is the same as that for access to=20
> members of
> dependent base classes: use 'this->' to make the expression dependent=20
> 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 i=
s
> treated exactly as if the mixin's code was directly embedded into the=20
> class,
> i.e. members prior to the mixin directive are visible, those after are=20
> not, and
> all the usual rules for ambiguity and changing meanings apply.
> Mixins can contain access declarations. Their members have the more=20
> restricted
> access of the one they have in the mixin and the one the mixin=20
> 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=20
> 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=20
> save on
> new keywords.
>
>
>
> Mixins can contain every kind of declaration that classes can,=20
> including inner
> types, data members, and more mixin directives. Mixins cannot have=20
> base classes.
> (POD: Should they be able to? The bases could be appended to the list=20
> 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=20
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=20
> 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=20
> class, and
> the random access mixin. I believe that the best resolution rules are:
> - Conflicting variables are an error, with the exception of static=20
> 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=20
on the base mixin. I see this is an advantage of the inheritance=20
approach respect to the member approach.
For example, several mixins could define a trace function that use the=20
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=20
> 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=20
> 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
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------000101060707090609000507
Content-Type: text/html; charset=ISO-8859-1
<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div class="moz-cite-prefix">Le 27/08/13 23:14, Sebastian Redl a
écrit :<br>
</div>
<blockquote
cite="mid:787081f7-fb40-4507-907d-259318ef2000@isocpp.org"
type="cite">
<div dir="ltr">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.<br>
<br>
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.<br>
<br>
<br>
=== Mixins (Class Extension Blocks) for C++ ===<br>
<br>
--- Purpose ---<br>
Create a solution for injecting repetitive code into classes
that has intuitive<br>
syntax, doesn't use the preprocessor, and lacks the drawbacks of
the CRTP.<br>
<br>
--- Background ---<br>
There's often a need for classes to contain somewhat repetitive
code. For the<br>
purpose of this document, we'll go with three motivating
examples, in<br>
increasing complexity.<br>
<br>
</div>
</blockquote>
Hi,<br>
<br>
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.<br>
<br>
<snip><br>
<blockquote
cite="mid:787081f7-fb40-4507-907d-259318ef2000@isocpp.org"
type="cite">
<div dir="ltr"><br>
Example 2: Repetitive Operators (Boost.Operators,
Boost.Iterator)<br>
If I want to define my own smart pointer, here's what I have to
do:<br>
<span style="font-family: courier new,monospace;">template
<typename T><br>
class my_ptr {<br>
// Custom storage logic.<br>
T* raw;<br>
public:<br>
// Custom construction and destruction logic.<br>
<br>
T* get() const {<br>
// Custom access logic.<br>
return raw;<br>
}<br>
<br>
// All these can be defined in terms of get():<br>
T& operator *() const { return *get(); }<br>
T* operator ->() const { return get(); }<br>
// This was worse in C++03, when the safe-bool idiom had to
be used.<br>
explicit operator bool() const { return get() != nullptr; }<br>
bool operator !() const { return get() == nullptr; }<br>
};<br>
</span><br>
Again, one could define a macro to encapsulate these operations,
or a base<br>
class. However, the base class solution has the problem that it
needs to access<br>
the get() function in the derived class. There are two possible
ways to deal<br>
with this.<br>
<br>
<snip<<br>
<br>
The second way is to use the Curiously Recurring Template
Pattern:<br>
<span style="font-family: courier new,monospace;">template
<typename Derived, typename T><br>
class smart_ptr_base {<br>
const Derived& self() const { return
*static_case<const Derived*>(this); }<br>
public:<br>
T& operator *() const { return *self().get(); }<br>
// etc.<br>
};<br>
template <typename T><br>
class my_ptr : public smart_ptr_base<my_ptr<T>, T>
{<br>
T* get() const { return raw; }<br>
};<br>
</span><br>
The drawbacks of this solution are:<br>
- The CRTP introduces its own boilerplate (the self() function).<br>
- The CRTP's workings are unintuitive to those introduced to it
- there's a<br>
reason it's called "curiously" recurring. In particular, the
fact that<br>
Derived is an incomplete type in the body of the CRTP class is
a common<br>
stumbling block, and the reason T must be passed along in the
above example<br>
instead of determined by examining Derived (e.g. to look at a
nested typedef).<br>
Function type deduction in C++14 can help in some cases, but
not all.<br>
- The class name must be repeated, including all its template
arguments - the<br>
injected-class-name is not yet visible in the base
specification.<br>
- The interface that the CRTP base uses from the derived class
must either be<br>
public, or there must be some friendship between the classes.
Specifying the<br>
entire base class in a friend declaration can be annoying, and
friending a<br>
type alias wasn't possible before C++11, which led to
workarounds such as<br>
iterator_core_access (from Boost.Iterator).<br>
<br>
</div>
</blockquote>
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.<br>
<br>
<span style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;">template
<typename Base><br>
</span></span></span></span><span style="font-family:
courier new,monospace;"><span style="font-family: courier
new,monospace;"><span style="font-family: courier
new,monospace;"><span style="font-family: courier
new,monospace;"><span style="font-family: courier
new,monospace;"><span style="font-family: courier
new,monospace;"></span></span></span></span></span></span></span></span>struct
self_mixin {<br>
</span><span style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;">template
<typename Derived><br>
</span> class type </span><span style="font-family: courier
new,monospace;"><span style="font-family: courier new,monospace;">:
public Base </span><br>
{<br>
</span><span style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;">public:<br>
using Base::Base;<br>
</span> protected:<br>
typedef Derived derived_type;<br>
</span><span style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"> const
Derived& self() const { return *static_cast<const
Derived*>(this); }<br>
</span></span><span style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"> Derived&
self() { return *static_cast<Derived*>(this); }<br>
</span></span> };<br>
};<br>
</span><br>
<br>
<span style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;">template
<typename T><br>
</span></span></span></span><span style="font-family:
courier new,monospace;"><span style="font-family: courier
new,monospace;"><span style="font-family: courier
new,monospace;"><span style="font-family: courier
new,monospace;"><span style="font-family: courier
new,monospace;"><span style="font-family: courier
new,monospace;"></span></span></span></span></span></span>class
smart_ptr_mixin <br>
{<br>
</span></span><span style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"> template
<typename Derived, typename Base><br>
</span></span> class type : public Base {<br>
</span></span><span style="font-family: courier
new,monospace;"><span style="font-family: courier
new,monospace;"><span style="font-family: courier
new,monospace;"><span style="font-family: courier
new,monospace;"></span></span></span></span></span></span><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"> public:<br>
using Base::Base;<br>
</span></span></span> public:<br>
T& operator *() const { return *self().get(); }<br>
// etc.<br>
</span></span><span style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"> };<br>
};</span></span><br>
<br>
The use of these mixins is done as<br>
<br>
<span style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;">template
<typename T><br>
class my_ptr : public mixins<</span></span><b><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;">my_ptr<T>, </span></span></b><b><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"></span></span></b><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><b><span
style="font-family: courier new,monospace;">self_mixin</span></b><b><></b>,
</span></span><span style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"></span></span><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;">smart_ptr_mixin<</span></span>T></span></span>
> <br>
{<br>
</span></span><span style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;">public:<br>
</span></span><span style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"> T* get() const {
return raw; }<br>
// ...<br>
};</span></span><br>
<br>
<br>
<span style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;">mixins has as
parameter the current class, and the list of mixins starting
from the base one.<br>
<br>
<br>
We could make define a MIXIN macro so that<br>
<br>
</span></span><br>
<span style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;">template
<typename T><br>
</span></span></span></span><b><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"></span></span></span></span></span></span></b><b>MIXIN(</b>smart_ptr_mixin)
<br>
{<br>
</span></span><span style="font-family: courier
new,monospace;"><span style="font-family: courier
new,monospace;">public:<br>
T& operator *() const { return *<b>self()</b>.get(); }<br>
// etc.<br>
</span></span><span style="font-family: courier
new,monospace;"><span style="font-family: courier
new,monospace;">};<br>
<br>
is equivalent to<br>
<br>
</span></span><br>
<span style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;">template
<typename T><br>
</span></span></span></span><b><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier
new,monospace;"></span></span></span></span></span></span></b><b>class
smart_ptr_mixin </b><b><br>
</b><b>
{</b><b><br>
</b></span></span><b><span style="font-family:
courier new,monospace;"><span style="font-family:
courier new,monospace;"><span style="font-family:
courier new,monospace;"><span style="font-family:
courier new,monospace;"><span style="font-family:
courier new,monospace;"><span
style="font-family: courier new,monospace;">template
<typename Derived, typename Base><br>
</span></span> class type : public Base {<br>
</span></span><span style="font-family: courier
new,monospace;"><span style="font-family: courier
new,monospace;"><span style="font-family: courier
new,monospace;"><span style="font-family:
courier new,monospace;"></span></span></span></span></span></span></b><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><b>
public:</b><b><br>
</b><b> using Base::Base;<br>
friend Derived;<br>
</b></span></span></span> public:<br>
T& operator *() const { return *<b>self()</b>.get();
}<br>
// etc.<br>
</span></span><span style="font-family: courier
new,monospace;"><span style="font-family: courier
new,monospace;"> };<br>
<b>};<br>
<br>
</b>This approach solve some of the drawbacks you
mention, while not all. <br>
The noise is in boldbace<b><br>
<br>
<br>
</b></span></span></span></span></span></span>
<blockquote
cite="mid:787081f7-fb40-4507-907d-259318ef2000@isocpp.org"
type="cite">
<div dir="ltr"><br>
<br>
--- Proposed Solution ---<br>
Introduce a new code construct, the "mixin". A mixin is similar
to a class, but<br>
is not a type by itself. Instead, a mixin is embedded in (mixed
into) a class;<br>
its members become members of the class. A mixin is implicitly
templated on the<br>
type that embeds it, but can in addition have further template
parameters. A<br>
mixin is embedded in a class with a "using mixin" directive.<br>
<br>
Example 1: Non-Copyable<br>
Here's a non-copyable mixin:<br>
<br>
<span style="font-family: courier new,monospace;">mixin
noncopyable {<br>
noncopyable(const noncopyable&) = delete;<br>
noncopyable& operator =(const noncopyable&) =
delete;<br>
}<br>
class foo {<br>
using mixin noncopyable;<br>
};<br>
</span><br>
Here, the compiler will fail to generate the copy functions for
foo, because<br>
they would have to call the mixin's copy functions, which are
deleted. The mixin<br>
acts like a data member here, including the order of
construction (i.e. when<br>
data members and mixins are mixed, the constructors are called
in the order of<br>
declaration).<br>
<br>
</div>
</blockquote>
Does making mixins act like data member makes then increase the size
of the class?<br>
Have you considered to see them as part of the inheritance hierarchy?<br>
<br>
<span style="font-family: courier new,monospace;">class foo : public
mixin X <br>
{<br>
};</span><br>
<blockquote
cite="mid:787081f7-fb40-4507-907d-259318ef2000@isocpp.org"
type="cite">
<div dir="ltr">Example 2: Repetitive Operators<br>
Here's the smart_ptr mixin:<br>
<br>
<span style="font-family: courier new,monospace;">mixin
smart_ptr {<br>
public:<br>
// Could use decltype(auto) in C++14, but in some cases we
can't, e.g. when<br>
// we want to use SFINAE tricks on some overloads.<br>
auto operator *() const -> decltype(*this->get()) {
return *this->get(); }<br>
auto operator ->() const -> decltype(this->get()) {
return this->get(); }<br>
explicit operator bool() const { return this->get() !=
nullptr; }<br>
bool operator !() const { return this->get() == nullptr;
}<br>
}<br>
template <typename T><br>
class my_ptr {<br>
public:<br>
T* get() const { return raw; }<br>
using mixin smart_ptr;<br>
};<br>
</span><br>
To make this work, we need rules about the access to the
embedding class from<br>
the mixin.<br>
Since the mixin is a template, the type of its 'this' pointer is
dependent.<br>
The syntax for acessing members is the same as that for access
to members of<br>
dependent base classes: use 'this->' to make the expression
dependent and delay<br>
lookup until instantiation time.<br>
</div>
</blockquote>
Have you considered adding a self keyword instead of using this?<br>
<blockquote
cite="mid:787081f7-fb40-4507-907d-259318ef2000@isocpp.org"
type="cite">
<div dir="ltr">When the mixin is instantiated, the completeness of
the embedding class is<br>
treated exactly as if the mixin's code was directly embedded
into the class,<br>
i.e. members prior to the mixin directive are visible, those
after are not, and<br>
all the usual rules for ambiguity and changing meanings apply.<br>
Mixins can contain access declarations. Their members have the
more restricted<br>
access of the one they have in the mixin and the one the mixin
directive is<br>
under. (POD: Just ignore the latter?)<br>
Mixins can access all members of the embedding class, even
private ones.<br>
<br>
Example 3: Polymorphic Cloning<br>
Here's the cloneable mixin:<br>
<br>
<span style="font-family: courier new,monospace;">mixin
cloneable {<br>
public:<br>
decltype(mixin)* clone() const override { return new
decltype(mixin)(*this); }<br>
}<br>
class foo : public base {<br>
public:<br>
using mixin cloneable;<br>
};<br>
</span><br>
Functions in the mixin override functions the embedding class
inherited.<br>
The 'decltype(mixin)' construct names the embedding class. This
is to save on<br>
new keywords.<br>
<br>
<br>
<br>
Mixins can contain every kind of declaration that classes can,
including inner<br>
types, data members, and more mixin directives. Mixins cannot
have base classes.<br>
(POD: Should they be able to? The bases could be appended to the
list of bases<br>
of the embedding class. What kind of problems could that cause?)<br>
</div>
</blockquote>
<br>
I don't see why the introduction of the last constraint is needed.
With the CRTP model there is no such limitation<br>
<br>
<span style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;">template
<typename T><br>
</span></span></span></span><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"></span></span></span></span></span></span>class
smart_ptr_mixin <br>
{<br>
</span></span><span style="font-family: courier
new,monospace;"><span style="font-family: courier
new,monospace;"><span style="font-family: courier
new,monospace;"><span style="font-family: courier
new,monospace;"><span style="font-family: courier
new,monospace;"><span style="font-family: courier
new,monospace;">template <typename Derived,
typename Base><br>
</span></span> class type : public Base, <b>smart_ptr_base</b>
{<br>
</span></span><span style="font-family: courier
new,monospace;"><span style="font-family: courier
new,monospace;"><span style="font-family: courier
new,monospace;"><span style="font-family: courier
new,monospace;"></span></span></span></span></span></span><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;"><span
style="font-family: courier new,monospace;">
public:<br>
using Base::Base;<br>
friend Derived;<b><br>
</b></span></span></span> public:<br>
T& operator *() const { return *self().get(); }<br>
// etc.<br>
</span></span><span style="font-family: courier
new,monospace;"><span style="font-family: courier
new,monospace;"> };<br>
<b>};</b></span></span></span></span></span></span><br>
<div dir="ltr"><br>
<snip><br>
</div>
<br>
<blockquote
cite="mid:787081f7-fb40-4507-907d-259318ef2000@isocpp.org"
type="cite">
<div dir="ltr">On a side note, name conflicts can arise between
the embedding class and mixins,<br>
especially for nested types defined for utility, e.g.
difference_type and<br>
reference in the example above are defined in both the embedding
class, and<br>
the random access mixin. I believe that the best resolution
rules are:<br>
- Conflicting variables are an error, with the exception of
static constants<br>
with known values, which get merged if the values are the
same.<br>
</div>
</blockquote>
I wouldn't consider this as an exception. <br>
<blockquote
cite="mid:787081f7-fb40-4507-907d-259318ef2000@isocpp.org"
type="cite">
<div dir="ltr">- Functions overload. If they cannot overload, it's
an error.<br>
</div>
</blockquote>
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.<br>
<br>
For example, several mixins could define a trace function that use
the base one and add something else<br>
<br>
void trace() {<br>
this->base_type.trace();<br>
// ....<br>
}<br>
<blockquote
cite="mid:787081f7-fb40-4507-907d-259318ef2000@isocpp.org"
type="cite">
<div dir="ltr">- Types are merged if they are the same type.<br>
<br>
In addition, it might be useful to make it possible for mixins
to have sections<br>
that are not made visible to the embedding class (e.g. a
"mixin:" access<br>
specifier), although I am hesitant to really do this, because I
can see a<br>
pattern developing where the entire class body is always put in
a mixin, and a<br>
mixin: specifier is used to create "truly hidden" private
sections.<br>
</div>
</blockquote>
Why using private as for class is not enough? What am I missing?<br>
<br>
Best,<br>
Vicente<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/</a>.<br />
--------------000101060707090609000507--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Sat, 31 Aug 2013 10:23:20 +0200
Raw View
This is a multi-part message in MIME format.
--------------030807000801040603040509
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 28/08/13 02:54, Sean Middleditch a =C3=A9crit :
> On Tuesday, August 27, 2013 4:59:34 PM UTC-7, R=C3=B3bert D=C4=AFvid wrot=
e:
>
> That is an incredibly simplistic example of the CRTP mixin pattern.=20
> Try a class that wants to use two mixins which each partially=20
> implement some of the polymorphic interface of a base. It gets=20
> unwieldly, quickly.
Could you show a concrete example and how the proposed mixin feature=20
would help?
>
>
> And then there's the weird recursive situations, which granted are=20
> very exceptional in a good design, but I've seen come up several time.=20
> Example:
>
> struct base {
> virtual base& foo() =3D 0;
> virtual base& bar() =3D 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,=20
> mixin_bar<mixin_foo<derived, ???>, base>>
> {
> int value =3D 5; // note that mixin_bar wants to use mixin_foo's=20
> 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() =3D 0;
> virtual base& foo() =3D 0;
> };
>
> There's no way to realistically fill in the ??? part as mixin_bar's=20
> Derived type is itself dependent on mixin_bar. Again, it's a weird=20
> case, and every time I've seen it myself I've found other (arguably=20
> much better) ways to do what I wanted, but it is a general pattern=20
> that C++ multiple inheritance and CRTP are not an alternative to=20
> mixins. You can't _compose mixins_ with CRTP.
>
Sorry I missed the mixin solution?
Best,
Vicente
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------030807000801040603040509
Content-Type: text/html; charset=ISO-8859-1
<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div class="moz-cite-prefix">Le 28/08/13 02:54, Sean Middleditch a
écrit :<br>
</div>
<blockquote
cite="mid:15e395b4-47f7-42b3-8eb2-93d113daa63a@isocpp.org"
type="cite">
<div dir="ltr">On Tuesday, August 27, 2013 4:59:34 PM UTC-7,
Róbert Dávid wrote:<br>
<br>
<div>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.</div>
</div>
</blockquote>
Could you show a concrete example and how the proposed mixin feature
would help?<br>
<blockquote
cite="mid:15e395b4-47f7-42b3-8eb2-93d113daa63a@isocpp.org"
type="cite">
<div dir="ltr">
<div> </div>
<br>
<div><br>
</div>
<div>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:</div>
<div><br>
</div>
<div> struct base {</div>
<div> virtual base& foo() = 0;<br>
</div>
<div> virtual base& bar() = 0;</div>
<div> };</div>
<div><br>
</div>
<div> template <class Derived, class Base></div>
<div> struct mixin_foo : public Base {</div>
<div> int value;</div>
<div> Derived& foo() override;</div>
<div> };</div>
<div><br>
</div>
<div> template <class Derived, class Base></div>
<div> struct mixin_bar : public Base {</div>
<div> void something(int);</div>
<div> Derived& bar() override {</div>
<div>
something(static_cast<Derived&>(*this).value);</div>
<div> return *this;</div>
<div> }</div>
<div> };</div>
<div><br>
</div>
<div> struct derived : publix mixin_foo<derived,
mixin_bar<mixin_foo<derived, ???>, base>></div>
<div> {</div>
<div> int value = 5; // note that mixin_bar wants to use
mixin_foo's value, not derived's value</div>
<div> };</div>
<div><br>
</div>
</div>
</blockquote>
Shouldn't this be <br>
<br>
<div> Derived& bar() override {</div>
<div> something(this-><b>Base</b>.value);</div>
<div> return *this;</div>
<div> }</div>
<br>
and<br>
<br>
<div> struct derived : publix mixin_bar<derived,
mixin_foo<derived, base>></div>
<br>
?<br>
<blockquote
cite="mid:15e395b4-47f7-42b3-8eb2-93d113daa63a@isocpp.org"
type="cite">
<div dir="ltr">
<div>Oppose this to a mixin solution:</div>
<div><br>
</div>
<div> struct base {</div>
<div> virtual base& foo() = 0;</div>
<div> virtual base& foo() = 0;</div>
<div> };</div>
<div><br>
</div>
<div>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.</div>
<div> <br>
</div>
</div>
</blockquote>
Sorry I missed the mixin solution?<br>
<br>
Best,<br>
Vicente<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/</a>.<br />
--------------030807000801040603040509--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Sat, 31 Aug 2013 10:24:59 +0200
Raw View
This is a multi-part message in MIME format.
--------------000502090600030806050303
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 28/08/13 02:59, Sean Middleditch a =E9crit :
> 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() =3D 0;
> virtual base& foo() =3D 0;
> };
>
>
> And I got distracted and cut short writing up that mixin example.
>
> struct base {
> virtual base& foo() =3D 0;
> virtual base& bar() =3D 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 =3D 5;
> };
>
> I'm not super fond of the syntax there, but the idea is illustrated as=20
> 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=20
and the proposed mixin approach.
Vicente
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------000502090600030806050303
Content-Type: text/html; charset=ISO-8859-1
<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div class="moz-cite-prefix">Le 28/08/13 02:59, Sean Middleditch a
écrit :<br>
</div>
<blockquote
cite="mid:ef7ec7d7-7e33-471f-b4c2-5e20625f0cd2@isocpp.org"
type="cite">
<div dir="ltr">On Tuesday, August 27, 2013 5:54:43 PM UTC-7, Sean
Middleditch wrote:<br>
<blockquote class="gmail_quote" style="margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div dir="ltr">
<div><br>
</div>
<div>Oppose this to a mixin solution:</div>
<div><br>
</div>
<div> struct base {</div>
<div> virtual base& foo() = 0;</div>
<div> virtual base& foo() = 0;</div>
<div> };</div>
</div>
</blockquote>
<div><br>
</div>
And I got distracted and cut short writing up that mixin
example.
<div><br>
</div>
<div>
<div> struct base {</div>
<div> virtual base& foo() = 0;</div>
<div> virtual base& bar() = 0;</div>
<div> };</div>
</div>
<div><br>
</div>
<div> struct mixin_foo mixin {</div>
<div> int value;</div>
<div> auto decltype(*this) foo();</div>
<div> };</div>
<div><br>
</div>
<div>
<div> struct mixin_bar mixin {<br>
</div>
<div> void something(int);</div>
<div> auto bar() {</div>
<div> something(this->value);</div>
<div> return *this;</div>
<div> }</div>
<div> };</div>
<div><br>
</div>
<div> struct derived : public base</div>
<div> {</div>
<div> using mixin mixin_foo;</div>
<div> using mixin mixin_bar { using mixin_foo::value; }
// sample syntax</div>
<div> int value = 5;</div>
<div> };</div>
</div>
<div><br>
</div>
<div>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.</div>
</div>
<br>
</blockquote>
Oh, I've got it now. I don't see too much difference between the
CRTP and the proposed mixin approach.<br>
<br>
Vicente <br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/</a>.<br />
--------------000502090600030806050303--
.
Author: cornedbee@google.com
Date: Mon, 2 Sep 2013 07:24:26 -0700 (PDT)
Raw View
------=_Part_1984_9083185.1378131866915
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On Saturday, August 31, 2013 8:59:19 AM UTC+2, Vicente J. Botet Escriba=20
wrote:
>
> Le 29/08/13 11:38, corn...@google.com <javascript:> a =E9crit :
> =20
>
>
> On Thursday, August 29, 2013 3:11:47 AM UTC+2, R=F3bert D=E1vid wrote:=20
>>
>>
>> Consider:
>> mixin noncopyable {
>> noncopyable(const noncopyable&) =3D delete;
>> };
>> struct Foo{
>> using mixin noncopyable;
>> };
>> struct Bar : public Foo {
>> Bar(const Bar&) : Foo() {}
>> }
>> Is Bar noncopyable (conflicting with the copy constructor definition,=
=20
>> making Bar ill-formed)?
>>
>> =20
> Bar is well-formed and copyable.
>
> This seems counter intuitive. If Foo is not copyable, Bar canot be=20
> copyable.
> =20
>
Why? You just explicitly defined that Bar's notion of copying is to=20
default-construct the Foo part of the object. If you explicitly define the=
=20
copy constructor for a class, that class is copyable; everything else would=
=20
be highly counter-intuitive.
=20
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_1984_9083185.1378131866915
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Saturday, August 31, 2013 8:59:19 AM UTC+2, Vic=
ente J. Botet Escriba wrote:<blockquote class=3D"gmail_quote" style=3D"marg=
in: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 29/08/13 11:38, <a href=3D"javascript:" target=3D"_blank" gdf-o=
bfuscated-mailto=3D"kBXbSWpoxtkJ">corn...@google.com</a>
a =E9crit :<br>
</div>
<blockquote type=3D"cite">
<div dir=3D"ltr"><br>
<br>
On Thursday, August 29, 2013 3:11:47 AM UTC+2, R=F3bert D=E1vid
wrote:
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir=3D"ltr"><br></div></blockquote></div></blockquote><block=
quote type=3D"cite"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex=
"><div dir=3D"ltr">
Consider:<br>
<div style=3D"background-color:rgb(250,250,250);border-color:rg=
b(187,187,187);border-style:solid;border-width:1px;word-wrap:break-word"><c=
ode>
<div><span style=3D"color:rgb(0,0,0)">mixin noncopyable </s=
pan><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0=
,0,0)"><br>
noncopyable</span><span style=3D"color:rgb(102,1=
02,0)">(</span><span style=3D"color:rgb(0,0,136)">const</span><span style=
=3D"color:rgb(0,0,0)"> noncopyable</span><span style=3D"color:rgb(102,102,0=
)">&)</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"col=
or:rgb(102,102,0)">=3D</span><span style=3D"color:rgb(0,0,0)"> </span><span=
style=3D"color:rgb(0,0,136)">delete</span><span style=3D"color:rgb(102,102=
,0)">;</span><span style=3D"color:rgb(0,0,0)"><br>
</span><span style=3D"color:rgb(102,102,0)">};</span><spa=
n style=3D"color:rgb(0,0,0)"><br>
</span><span style=3D"color:rgb(0,0,136)">struct</span><s=
pan style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)"=
>Foo</span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"colo=
r:rgb(0,0,0)"><br>
</span><span style=3D"color:rgb(0,0,136)">using<=
/span><span style=3D"color:rgb(0,0,0)"> mixin noncopyable</span><span style=
=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"><br>
</span><span style=3D"color:rgb(102,102,0)">};</span><spa=
n style=3D"color:rgb(0,0,0)"><br>
</span><code><span style=3D"color:rgb(0,0,136)">struct</s=
pan><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0=
,102)"></span></code><span style=3D"color:rgb(102,0,102)">Bar</span><span s=
tyle=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">:</s=
pan><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,1=
36)">public</span><span style=3D"color:rgb(0,0,0)"> Foo {<br>
Bar(const Bar&) : Foo() {}<br>
}<br>
</span></div>
</code></div>
Is Bar noncopyable (conflicting with the copy constructor
definition, making Bar ill-formed)?<br>
<br>
</div>
</blockquote>
<div><br>
</div>
<div>Bar is well-formed and copyable.</div>
<br>
</div>
</blockquote>
This seems counter intuitive. If Foo is not copyable, Bar canot be
copyable.<br> <br></div></blockquote><div><br></div><div>Why? You =
just explicitly defined that Bar's notion of copying is to default-construc=
t 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 count=
er-intuitive.</div><div> </div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1984_9083185.1378131866915--
.
Author: cornedbee@google.com
Date: Mon, 2 Sep 2013 07:51:21 -0700 (PDT)
Raw View
------=_Part_2086_27618098.1378133481091
Content-Type: text/plain; charset=ISO-8859-1
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.
--
---
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2086_27618098.1378133481091
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Saturday, August 31, 2013 9:50:25 AM UTC+2, Vic=
ente J. Botet Escriba wrote:<blockquote class=3D"gmail_quote" style=3D"marg=
in: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><d=
iv bgcolor=3D"#FFFFFF" text=3D"#000000">
Hi,<br>
<br>
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.<br>
<br></div></blockquote><div><br></div><div>Hi Vicente,</div><div><br></=
div><div>Thanks for all the feedback.</div><div> </div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #=
ccc solid;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF" text=3D"#000000">
<snip><br>
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.<br>
<br>
<span style=3D"font-family:courier new,monospace"><span style=3D"font-f=
amily:courier new,monospace"><span style=3D"font-family:courier new,monospa=
ce"><span style=3D"font-family:courier new,monospace"><span style=3D"font-f=
amily:courier new,monospace"><span style=3D"font-family:courier new,monospa=
ce"><span style=3D"font-family:courier new,monospace">template
<typename Base><br>
</span></span></span></span><span style=3D"font-family:cour=
ier new,monospace"><span style=3D"font-family:courier new,monospace"><span =
style=3D"font-family:courier new,monospace"><span style=3D"font-family:cour=
ier new,monospace"><span style=3D"font-family:courier new,monospace"><span =
style=3D"font-family:courier new,monospace"></span></span></span></span></s=
pan></span></span></span>struct
self_mixin {<br>
</span><span style=3D"font-family:courier new,monospace"><span style=3D=
"font-family:courier new,monospace">template
<typename Derived><br>
</span> class type </span><span style=3D"font-family:courier ne=
w,monospace"><span style=3D"font-family:courier new,monospace">:
public Base </span><br>
{<br>
</span><span style=3D"font-family:courier new,monospace"><span style=3D=
"font-family:courier new,monospace">public:<br>
using Base::Base;<br>
</span> protected:<br>
typedef Derived derived_type;<br>
</span><span style=3D"font-family:courier new,monospace"><span style=3D=
"font-family:courier new,monospace"> const
Derived& self() const { return *static_cast<const
Derived*>(this); }<br>
</span></span><span style=3D"font-family:courier new,monospace"><span=
style=3D"font-family:courier new,monospace"><span style=3D"font-family:cou=
rier new,monospace"> Derived&
self() { return *static_cast<Derived*>(this); }<br>
</span></span> };<br>
};<br>
</span><br>
<br>
<span style=3D"font-family:courier new,monospace"><span style=3D"font-f=
amily:courier new,monospace"><span style=3D"font-family:courier new,monospa=
ce"><span style=3D"font-family:courier new,monospace"><span style=3D"font-f=
amily:courier new,monospace"><span style=3D"font-family:courier new,monospa=
ce">template
<typename T><br>
</span></span></span></span><span style=3D"font-family:courie=
r new,monospace"><span style=3D"font-family:courier new,monospace"><span st=
yle=3D"font-family:courier new,monospace"><span style=3D"font-family:courie=
r new,monospace"><span style=3D"font-family:courier new,monospace"><span st=
yle=3D"font-family:courier new,monospace"></span></span></span></span></spa=
n></span>class
smart_ptr_mixin <br>
{<br>
</span></span><span style=3D"font-family:courier new,monospace"><span=
style=3D"font-family:courier new,monospace"><span style=3D"font-family:cou=
rier new,monospace"><span style=3D"font-family:courier new,monospace"><span=
style=3D"font-family:courier new,monospace"><span style=3D"font-family:cou=
rier new,monospace"> template
<typename Derived, typename Base><br>
</span></span> class type : public Base {<br>
</span></span><span style=3D"font-family:courier new,monospace"><=
span style=3D"font-family:courier new,monospace"><span style=3D"font-family=
:courier new,monospace"><span style=3D"font-family:courier new,monospace"><=
/span></span></span></span></span></span><span style=3D"font-family:courier=
new,monospace"><span style=3D"font-family:courier new,monospace"><span sty=
le=3D"font-family:courier new,monospace"><span style=3D"font-family:courier=
new,monospace"><span style=3D"font-family:courier new,monospace"> pu=
blic:<br>
using Base::Base;<br>
</span></span></span> public:<br>
T& operator *() const { return *self().get()=
; }<br></span></span></div></blockquote><div><br></div><div>Nit: must be 'r=
eturn *this->self().get();'</div><div> </div><blockquote class=3D"g=
mail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc sol=
id;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF" text=3D"#000000"><span styl=
e=3D"font-family:courier new,monospace"><span style=3D"font-family:courier =
new,monospace">
// etc.<br>
</span></span><span style=3D"font-family:courier new,monospace"><span=
style=3D"font-family:courier new,monospace"> };<br>
};</span></span><br>
<br>
The use of these mixins is done as<br>
<br>
<span style=3D"font-family:courier new,monospace"><span style=3D"font-f=
amily:courier new,monospace">template
<typename T><br>
class my_ptr : public mixins<</span></span><b><span style=3D"fon=
t-family:courier new,monospace"><span style=3D"font-family:courier new,mono=
space">my_ptr<T>, </span></span></b><b><span style=3D"font-famil=
y:courier new,monospace"><span style=3D"font-family:courier new,monospace">=
</span></span></b><span style=3D"font-family:courier new,monospace"><span s=
tyle=3D"font-family:courier new,monospace"><b><span style=3D"font-family:co=
urier new,monospace">self_mixin</span></b><b><></b><wbr>,
</span></span><span style=3D"font-family:courier new,monospace"><span=
style=3D"font-family:courier new,monospace"><span style=3D"font-family:cou=
rier new,monospace"><span style=3D"font-family:courier new,monospace"></spa=
n></span><span style=3D"font-family:courier new,monospace"><span style=3D"f=
ont-family:courier new,monospace"><span style=3D"font-family:courier new,mo=
nospace"><span style=3D"font-family:courier new,monospace">smart_ptr_mixin&=
lt;</span></span>T></span></span>
> <br>
{<br>
</span></span><span style=3D"font-family:courier new,monospace"><span=
style=3D"font-family:courier new,monospace">public:<br>
</span></span><span style=3D"font-family:courier new,monospace"><span=
style=3D"font-family:courier new,monospace"> T* get() const {
return raw; }<br>
// ...<br>
};</span></span><br>
<br>
<br>
<span style=3D"font-family:courier new,monospace"><span style=3D"font-f=
amily:courier new,monospace">mixins has as
parameter the current class, and the list of mixins starting
from the base one.<br></span></span></div></blockquote><div><br></d=
iv><div>I have actually developed a very similar system at one point, altho=
ugh it was C++03 and bound to one specific use case (which fixed the constr=
uctors and put a bound on the number of possible mixins, otherwise it would=
have been just horrible). It was still incredibly awkward to use, especial=
ly since I needed it in the public interface of the library I was developin=
g at the time; people writing additional components within my framework wou=
ld have had to use it. It was so bad that I scrapped the design completely.=
</div><div><br></div><div>Nested templates are simply ugly, and that's with=
out 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 ha=
ve never seen in production code, much less written.</div><div> <br></=
div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex=
;border-left: 1px #ccc solid;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF" t=
ext=3D"#000000"><span style=3D"font-family:courier new,monospace"><span sty=
le=3D"font-family:courier new,monospace">We could make define a MIXIN macro=
so that<br>
<br>
</span></span><br>
<span style=3D"font-family:courier new,monospace"><span style=3D"font-f=
amily:courier new,monospace"><span style=3D"font-family:courier new,monospa=
ce"><span style=3D"font-family:courier new,monospace"><span style=3D"font-f=
amily:courier new,monospace"><span style=3D"font-family:courier new,monospa=
ce"><span style=3D"font-family:courier new,monospace"><span style=3D"font-f=
amily:courier new,monospace">template
<typename T><br>
</span></span></span></span><b><span style=3D"font-family=
:courier new,monospace"><span style=3D"font-family:courier new,monospace"><=
span style=3D"font-family:courier new,monospace"><span style=3D"font-family=
:courier new,monospace"><span style=3D"font-family:courier new,monospace"><=
span style=3D"font-family:courier new,monospace"></span></span></span></spa=
n></span></span></b><b>MIXIN(</b>smart_ptr_mixin)
<br>
{<br>
</span></span><span style=3D"font-family:courier new,monospace"><=
span style=3D"font-family:courier new,monospace">public:<br>
T& operator *() const { return *<b>self()</b>.get();=
}<br>
// etc.<br>
</span></span><span style=3D"font-family:courier new,monospace"><=
span style=3D"font-family:courier new,monospace">};<br>
<br>
is equivalent to<br>
<br>
</span></span><br>
<span style=3D"font-family:courier new,monospace"><span style=3D"fo=
nt-family:courier new,monospace"><span style=3D"font-family:courier new,mon=
ospace"><span style=3D"font-family:courier new,monospace"><span style=3D"fo=
nt-family:courier new,monospace"><span style=3D"font-family:courier new,mon=
ospace"><span style=3D"font-family:courier new,monospace"><span style=3D"fo=
nt-family:courier new,monospace">template
<typename T><br>
</span></span></span></span><b><span style=3D"font-fa=
mily:courier new,monospace"><span style=3D"font-family:courier new,monospac=
e"><span style=3D"font-family:courier new,monospace"><span style=3D"font-fa=
mily:courier new,monospace"><span style=3D"font-family:courier new,monospac=
e"><span style=3D"font-family:courier new,monospace"></span></span></span><=
/span></span></span></b><b>class
smart_ptr_mixin </b><b><br>
</b><b>
{</b><b><br>
</b></span></span><b><span style=3D"font-family:co=
urier new,monospace"><span style=3D"font-family:courier new,monospace"><spa=
n style=3D"font-family:courier new,monospace"><span style=3D"font-family:co=
urier new,monospace"><span style=3D"font-family:courier new,monospace"><spa=
n style=3D"font-family:courier new,monospace">template
<typename Derived, typename Base><br>
</span></span> class type : public Base {<br>
</span></span><span style=3D"font-family:courier new,mo=
nospace"><span style=3D"font-family:courier new,monospace"><span style=3D"f=
ont-family:courier new,monospace"><span style=3D"font-family:courier new,mo=
nospace"></span></span></span></span></span></span></b><span style=3D"font-=
family:courier new,monospace"><span style=3D"font-family:courier new,monosp=
ace"><span style=3D"font-family:courier new,monospace"><span style=3D"font-=
family:courier new,monospace"><span style=3D"font-family:courier new,monosp=
ace"><b>
public:</b><b><br>
</b><b> using Base::Base;<br>
friend Derived;<br>
</b></span></span></span> public:<br>
T& operator *() const { return *<b>s=
elf()</b>.get();
}<br>
// etc.<br>
</span></span><span style=3D"font-family:courier new,monospac=
e"><span style=3D"font-family:courier new,monospace"> };<br>
<b>};<br></b></span></span></span></span></span></span></di=
v></blockquote><div><br></div><div>No, you actually can't. You can't genera=
te the second closing brace from the macro. You could define the macro to e=
xpand to something like</div><div><br></div><div>class NAME {</div><div>&nb=
sp; template <typename Derived, typename Base> class type;</div><div>=
};</div><div>template <typename Derived, typename Base> class NAME::t=
ype /* user continues here */</div><div><br></div><div>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.</div><div><br></div><div> </div><bl=
ockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border=
-left: 1px #ccc solid;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF" text=3D"=
#000000"><span style=3D"font-family:courier new,monospace"><span style=3D"f=
ont-family:courier new,monospace"><span style=3D"font-family:courier new,mo=
nospace"><span style=3D"font-family:courier new,monospace"><span style=3D"f=
ont-family:courier new,monospace"><span style=3D"font-family:courier new,mo=
nospace"><b>
<br>
</b>This approach solve some of the drawbacks you
mention, while not all. <br>
<b></b></span></span></span></span></span></span></div></bl=
ockquote><div><br></div><div>I don't really thinks it solves any of the dra=
wbacks. The boilerplate may be somewhat reduced, if you manage to write the=
macro, but all the other points in my list remain unaffected.</div><div>&n=
bsp;</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:=
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div bgcolor=3D"#FFF=
FFF" text=3D"#000000">
Does making mixins act like data member makes then increase the size
of the class?<br>
Have you considered to see them as part of the inheritance hierarchy?<b=
r></div></blockquote><div><br></div><div>Mixins don't act like data members=
for any purpose but construction/destruction.</div><div> </div><block=
quote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-le=
ft: 1px #ccc solid;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF" text=3D"#00=
0000">
<br>
<span style=3D"font-family:courier new,monospace">class foo : public
mixin X <br>
{<br>
};</span></div></blockquote><div><br></div><div>This runs into the pr=
oblems I mentioned about the completeness of foo within the mixin.</div><di=
v> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div bgcolor=3D"=
#FFFFFF" text=3D"#000000"><blockquote type=3D"cite"><div dir=3D"ltr">
Since the mixin is a template, the type of its 'this' pointer is
dependent.<br>
The syntax for acessing members is the same as that for access
to members of<br>
dependent base classes: use 'this->' to make the expression
dependent and delay<br>
lookup until instantiation time.<br>
</div>
</blockquote>
Have you considered adding a self keyword instead of using this?<br></d=
iv></blockquote><div><br></div><div>For a moment, but I don't see the point=
.. 'self' is completely impossible to add, since it is widely used as a vari=
able/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 ab=
out them, though.</div><div> </div><blockquote class=3D"gmail_quote" s=
tyle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-le=
ft: 1ex;"><div bgcolor=3D"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr"><br>
Mixins can contain every kind of declaration that classes can,
including inner<br>
types, data members, and more mixin directives. Mixins cannot
have base classes.<br>
(POD: Should they be able to? The bases could be appended to the
list of bases<br>
of the embedding class. What kind of problems could that cause?)<br=
>
</div>
</blockquote>
<br>
I don't see why the introduction of the last constraint is needed.
With the CRTP model there is no such limitation<br></div></blockquote><=
div><br></div><div>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 t=
he body.</div><div> </div><blockquote class=3D"gmail_quote" style=3D"m=
argin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"=
><div bgcolor=3D"#FFFFFF" text=3D"#000000"><blockquote type=3D"cite"><div d=
ir=3D"ltr">- Functions overload. If they cannot overload, it's
an error.<br>
</div>
</blockquote>
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.<br>
<br>
For example, several mixins could define a trace function that use
the base one and add something else<br>
<br>
void trace() {<br>
this->base_type.trace();<br>
// ....<br>
}<br></div></blockquote><div><br></div><div>This is a good point. Relay=
ing calls from one mixin to another is a use case I haven't considered so f=
ar. I have no good solution for this at the moment.</div><div> </div><=
blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bord=
er-left: 1px #ccc solid;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF" text=
=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr">In addition, it might be useful to make it possible =
for mixins
to have sections<br>
that are not made visible to the embedding class (e.g. a
"mixin:" access<br>
specifier), although I am hesitant to really do this, because I
can see a<br>
pattern developing where the entire class body is always put in
a mixin, and a<br>
mixin: specifier is used to create "truly hidden" private
sections.<br>
</div>
</blockquote>
Why using private as for class is not enough? What am I missing?<br></d=
iv></blockquote><div><br></div><div>In the base class model, conflicting na=
mes just hide each other; they are not by themselves an error. But going wi=
th the model of inheriting conflicting names from multiple bases might be t=
he best model for what I want to achieve after all. <br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2086_27618098.1378133481091--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Mon, 02 Sep 2013 19:22:22 +0200
Raw View
This is a multi-part message in MIME format.
--------------060104070406060705060608
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 02/09/13 16:24, cornedbee@google.com a =E9crit :
>
>
> On Saturday, August 31, 2013 8:59:19 AM UTC+2, Vicente J. Botet=20
> Escriba wrote:
>
> Le 29/08/13 11:38, corn...@google.com <javascript:> a =E9crit :
>>
>>
>> On Thursday, August 29, 2013 3:11:47 AM UTC+2, R=F3bert D=E1vid wrot=
e:
>>
>>
>> Consider:
>> |
>> mixin noncopyable {
>> noncopyable(constnoncopyable&)=3Ddelete;
>> };
>> structFoo{
>> usingmixin noncopyable;
>> };
>> |struct|Bar:publicFoo {
>> 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.
>
>
> Why? You just explicitly defined that Bar's notion of copying is to=20
> default-construct the Foo part of the object. If you explicitly define=20
> the copy constructor for a class, that class is copyable; everything=20
> else would be highly counter-intuitive.
>
Agreed. I miss that the default Foo() constructor was called.
Vicente
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------060104070406060705060608
Content-Type: text/html; charset=ISO-8859-1
<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div class="moz-cite-prefix">Le 02/09/13 16:24, <a class="moz-txt-link-abbreviated" href="mailto:cornedbee@google.com">cornedbee@google.com</a>
a écrit :<br>
</div>
<blockquote
cite="mid:fd681dd2-c4dc-429d-96fd-4442b5122f9f@isocpp.org"
type="cite">
<div dir="ltr"><br>
<br>
On Saturday, August 31, 2013 8:59:19 AM UTC+2, Vicente J. Botet
Escriba wrote:
<blockquote class="gmail_quote" style="margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor="#FFFFFF" text="#000000">
<div>Le 29/08/13 11:38, <a moz-do-not-send="true"
href="javascript:" target="_blank"
gdf-obfuscated-mailto="kBXbSWpoxtkJ">corn...@google.com</a>
a écrit :<br>
</div>
<blockquote type="cite">
<div dir="ltr"><br>
<br>
On Thursday, August 29, 2013 3:11:47 AM UTC+2, Róbert
Dávid wrote:
<blockquote class="gmail_quote"
style="margin:0;margin-left:0.8ex;border-left:1px #ccc
solid;padding-left:1ex">
<div dir="ltr"><br>
</div>
</blockquote>
</div>
</blockquote>
<blockquote type="cite">
<div dir="ltr">
<blockquote class="gmail_quote"
style="margin:0;margin-left:0.8ex;border-left:1px #ccc
solid;padding-left:1ex">
<div dir="ltr"> Consider:<br>
<div
style="background-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:break-word"><code>
<div><span style="color:rgb(0,0,0)">mixin
noncopyable </span><span
style="color:rgb(102,102,0)">{</span><span
style="color:rgb(0,0,0)"><br>
noncopyable</span><span
style="color:rgb(102,102,0)">(</span><span
style="color:rgb(0,0,136)">const</span><span
style="color:rgb(0,0,0)"> noncopyable</span><span
style="color:rgb(102,102,0)">&)</span><span
style="color:rgb(0,0,0)"> </span><span
style="color:rgb(102,102,0)">=</span><span
style="color:rgb(0,0,0)"> </span><span
style="color:rgb(0,0,136)">delete</span><span
style="color:rgb(102,102,0)">;</span><span
style="color:rgb(0,0,0)"><br>
</span><span style="color:rgb(102,102,0)">};</span><span
style="color:rgb(0,0,0)"><br>
</span><span style="color:rgb(0,0,136)">struct</span><span
style="color:rgb(0,0,0)"> </span><span
style="color:rgb(102,0,102)">Foo</span><span
style="color:rgb(102,102,0)">{</span><span
style="color:rgb(0,0,0)"><br>
</span><span style="color:rgb(0,0,136)">using</span><span
style="color:rgb(0,0,0)"> mixin noncopyable</span><span
style="color:rgb(102,102,0)">;</span><span
style="color:rgb(0,0,0)"><br>
</span><span style="color:rgb(102,102,0)">};</span><span
style="color:rgb(0,0,0)"><br>
</span><code><span style="color:rgb(0,0,136)">struct</span><span
style="color:rgb(0,0,0)"> </span><span
style="color:rgb(102,0,102)"></span></code><span
style="color:rgb(102,0,102)">Bar</span><span
style="color:rgb(0,0,0)"> </span><span
style="color:rgb(102,102,0)">:</span><span
style="color:rgb(0,0,0)"> </span><span
style="color:rgb(0,0,136)">public</span><span
style="color:rgb(0,0,0)"> Foo {<br>
Bar(const Bar&) : Foo() {}<br>
}<br>
</span></div>
</code></div>
Is Bar noncopyable (conflicting with the copy
constructor definition, making Bar ill-formed)?<br>
<br>
</div>
</blockquote>
<div><br>
</div>
<div>Bar is well-formed and copyable.</div>
<br>
</div>
</blockquote>
This seems counter intuitive. If Foo is not copyable, Bar
canot be copyable.<br>
<br>
</div>
</blockquote>
<div><br>
</div>
<div>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.</div>
<div> </div>
</div>
<br>
</blockquote>
Agreed. I miss that the default Foo() constructor was called.<br>
<br>
Vicente<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/</a>.<br />
--------------060104070406060705060608--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Mon, 02 Sep 2013 19:22:37 +0200
Raw View
This is a multi-part message in MIME format.
--------------070207030006060406090300
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 02/09/13 16:51, cornedbee@google.com a =E9crit :
>
>
> On Saturday, August 31, 2013 9:50:25 AM UTC+2, Vicente J. Botet=20
> 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();'
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=20
> it was C++03 and bound to one specific use case (which fixed the=20
> constructors and put a bound on the number of possible mixins,=20
> otherwise it would have been just horrible). It was still incredibly=20
> awkward to use, especially since I needed it in the public interface=20
> of the library I was developing at the time; people writing additional=20
> components within my framework would have had to use it. It was so bad=20
> that I scrapped the design completely.
>
> Nested templates are simply ugly, and that's without trying to define=20
> some of the mixin's methods out-of-line; then you get to multiple=20
> template parameter lists, which I bet 90% of C++ programmers have=20
> 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=20
> 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=20
> continues here */
>
> but that breaks for mixin templates, which require you to give the=20
> template parameter list and argument list forms to the macro, and then=20
> you run into the usual problems with commas in angle brackets in macro=20
> 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=20
> may be somewhat reduced, if you manage to write the macro, but all the=20
> other points in my list remain unaffected.
I'm not proposing these macros. I'm just seen how close a mixin=20
implementation (compiler) to a CRTP model it could be. The advantage is=20
that the model is well known, and so the new feature will be only=20
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=20
> construction/destruction.
OK.
>
>
> class foo : public mixin X
> {
> };
>
>
> This runs into the problems I mentioned about the completeness of foo=20
> within the mixin.
I don't see this as a problem, but a future of mixins. A mixin has only=20
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=20
> impossible to add, since it is widely used as a variable/function=20
> name, and the new use would be in a context where a variable name can=20
> appear. If you know any other conveniently short and logical words=20
> that aren't already in wide use in expression context, I'd love to=20
> 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=20
> to think about too hard. I would have to decide on the order of=20
> initialization, and from a compiler writer viewpoint, I'm not sure=20
> what it would mean to change the inheritance graph of a class in the=20
> 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=20
> use case I haven't considered so far. I have no good solution for this=20
> 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=20
> are not by themselves an error. But going with the model of inheriting=20
> conflicting names from multiple bases might be the best model for what=20
> I want to achieve after all.
Sorry, I don't understand. Are you telling inheriting from multiple bases?
Best,
Vicente
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------070207030006060406090300
Content-Type: text/html; charset=ISO-8859-1
<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div class="moz-cite-prefix">Le 02/09/13 16:51, <a class="moz-txt-link-abbreviated" href="mailto:cornedbee@google.com">cornedbee@google.com</a>
a écrit :<br>
</div>
<blockquote
cite="mid:15667a97-e6f3-46fb-b346-6f248b5815cf@isocpp.org"
type="cite">
<div dir="ltr"><br>
<br>
On Saturday, August 31, 2013 9:50:25 AM UTC+2, Vicente J. Botet
Escriba wrote:
<blockquote class="gmail_quote" style="margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor="#FFFFFF" text="#000000"> Hi,<br>
<br>
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.<br>
<br>
</div>
</blockquote>
<div><br>
</div>
<div>Hi Vicente,</div>
<div><br>
</div>
<div>Thanks for all the feedback.</div>
<div> </div>
<blockquote class="gmail_quote" style="margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor="#FFFFFF" text="#000000"> <snip><br>
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.<br>
<br>
<span style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace">template
<typename Base><br>
</span></span></span></span><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"></span></span></span></span></span></span></span></span>struct
self_mixin {<br>
</span><span style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace">template
<typename Derived><br>
</span> class type </span><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace">: public Base
</span><br>
{<br>
</span><span style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace">public:<br>
using Base::Base;<br>
</span> protected:<br>
typedef Derived derived_type;<br>
</span><span style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"> const
Derived& self() const { return *static_cast<const
Derived*>(this); }<br>
</span></span><span style="font-family:courier
new,monospace"><span style="font-family:courier
new,monospace"><span style="font-family:courier
new,monospace"> Derived& self() { return
*static_cast<Derived*>(this); }<br>
</span></span> };<br>
};<br>
</span><br>
<br>
<span style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace">template
<typename T><br>
</span></span></span></span><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"></span></span></span></span></span></span>class
smart_ptr_mixin <br>
{<br>
</span></span><span style="font-family:courier
new,monospace"><span style="font-family:courier
new,monospace"><span style="font-family:courier
new,monospace"><span style="font-family:courier
new,monospace"><span style="font-family:courier
new,monospace"><span style="font-family:courier
new,monospace"> template <typename Derived,
typename Base><br>
</span></span> class type : public Base {<br>
</span></span><span style="font-family:courier
new,monospace"><span style="font-family:courier
new,monospace"><span style="font-family:courier
new,monospace"><span style="font-family:courier
new,monospace"></span></span></span></span></span></span><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace">
public:<br>
using Base::Base;<br>
</span></span></span> public:<br>
T& operator *() const { return *self().get(); }<br>
</span></span></div>
</blockquote>
<div><br>
</div>
<div>Nit: must be 'return *this->self().get();'</div>
</div>
</blockquote>
Hrr, you are right. this-> is needed inside the template.<br>
<blockquote
cite="mid:15667a97-e6f3-46fb-b346-6f248b5815cf@isocpp.org"
type="cite">
<div dir="ltr">
<div> </div>
<blockquote class="gmail_quote" style="margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor="#FFFFFF" text="#000000"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"> // etc.<br>
</span></span><span style="font-family:courier
new,monospace"><span style="font-family:courier
new,monospace"> };<br>
};</span></span><br>
<br>
The use of these mixins is done as<br>
<br>
<span style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace">template
<typename T><br>
class my_ptr : public mixins<</span></span><b><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace">my_ptr<T>, </span></span></b><b><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"></span></span></b><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><b><span
style="font-family:courier new,monospace">self_mixin</span></b><b><></b><wbr>,
</span></span><span style="font-family:courier
new,monospace"><span style="font-family:courier
new,monospace"><span style="font-family:courier
new,monospace"><span style="font-family:courier
new,monospace"></span></span><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace">smart_ptr_mixin<</span></span>T></span></span>
> <br>
{<br>
</span></span><span style="font-family:courier
new,monospace"><span style="font-family:courier
new,monospace">public:<br>
</span></span><span style="font-family:courier
new,monospace"><span style="font-family:courier
new,monospace"> T* get() const { return raw; }<br>
// ...<br>
};</span></span><br>
<br>
<br>
<span style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace">mixins has as
parameter the current class, and the list of mixins
starting from the base one.<br>
</span></span></div>
</blockquote>
<div><br>
</div>
<div>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.</div>
<div><br>
</div>
<div>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.</div>
</div>
</blockquote>
Why would you need to define the mixin's methods out-of-line?
<blockquote
cite="mid:15667a97-e6f3-46fb-b346-6f248b5815cf@isocpp.org"
type="cite">
<div dir="ltr">
<div> <br>
</div>
<blockquote class="gmail_quote" style="margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor="#FFFFFF" text="#000000"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace">We could make
define a MIXIN macro so that<br>
<br>
</span></span><br>
<span style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace">template
<typename T><br>
</span></span></span></span><b><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier
new,monospace"><span
style="font-family:courier
new,monospace"></span></span></span></span></span></span></b><b>MIXIN(</b>smart_ptr_mixin)
<br>
{<br>
</span></span><span style="font-family:courier
new,monospace"><span style="font-family:courier
new,monospace">public:<br>
T& operator *() const { return *<b>self()</b>.get();
}<br>
// etc.<br>
</span></span><span style="font-family:courier
new,monospace"><span style="font-family:courier
new,monospace">};<br>
<br>
is equivalent to<br>
<br>
</span></span><br>
<span style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier
new,monospace">template <typename
T><br>
</span></span></span></span><b><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier
new,monospace"><span
style="font-family:courier
new,monospace"><span
style="font-family:courier
new,monospace"><span
style="font-family:courier
new,monospace"></span></span></span></span></span></span></b><b>class
smart_ptr_mixin </b><b><br>
</b><b> {</b><b><br>
</b></span></span><b><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier
new,monospace"><span
style="font-family:courier
new,monospace">template <typename
Derived, typename Base><br>
</span></span> class type : public Base
{<br>
</span></span><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier
new,monospace"><span
style="font-family:courier
new,monospace"></span></span></span></span></span></span></b><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><b>
public:</b><b><br>
</b><b> using Base::Base;<br>
friend Derived;<br>
</b></span></span></span> public:<br>
T& operator *() const { return *<b>self()</b>.get();
}<br>
// etc.<br>
</span></span><span style="font-family:courier
new,monospace"><span style="font-family:courier
new,monospace"> };<br>
<b>};<br>
</b></span></span></span></span></span></span></div>
</blockquote>
<div><br>
</div>
<div>No, you actually can't. You can't generate the second
closing brace from the macro. </div>
</div>
</blockquote>
Right. You can try then with<br>
<br>
<span style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace">template
<typename T><br>
</span></span></span></span><b><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"></span></span></span></span></span></span></b><b>MIXIN_BEGIN(</b>smart_ptr_mixin)
<br>
</span></span><span style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace">public:<br>
T& operator *() const { return *<b>self()</b>.get(); }<br>
// etc.<br>
</span></span><span style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"></span></span></span></span><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"></span></span></span></span><b><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier
new,monospace"><span
style="font-family:courier
new,monospace"></span></span></span></span></span></span></b><b>MIXIN_END</b></span></span></span></span>;<br>
<br>
I agree that don't having the braces is ugly.<br>
<br>
Alternatively you can do<br>
</span></span></span></span><br>
<span style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace">template
<typename T><br>
class </span></span></span></span>smart_ptr_mixin<br>
{<br>
<b>MIXIN_BEGIN;</b><br>
</span></span><span style="font-family:courier
new,monospace"><span style="font-family:courier new,monospace">public:<br>
T& operator *() const { return *<b>self()</b>.get(); }<br>
// etc.<br>
</span></span></span></span><span style="font-family:courier
new,monospace"><span style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"> <b>MIXIN_END;</b><br>
</span></span></span></span>}</span></span></span></span><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace">;<br>
<br>
that could expand to<br>
</span></span></span></span><br>
<span style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"> <span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace">template
<typename T><br>
</span></span></span></span><b><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"></span></span></span></span></span></span></b>class
smart_ptr_mixin <br>
{<br>
<b> </b></span></span><b><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace">template
<typename Derived, typename Base><br>
</span></span> class type : public Base {<br>
</span></span><span style="font-family:courier
new,monospace"><span style="font-family:courier
new,monospace"><span style="font-family:courier
new,monospace"><span style="font-family:courier
new,monospace"></span></span></span></span></span></span></b><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><b>
public:</b><b><br>
</b><b> using Base::Base;<br>
</b></span></span></span></span></span></span></span></span></span><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><b><span
style="font-family:courier new,monospace">
typedef Derived derived_type;<br>
</span><span style="font-family:courier
new,monospace"><span
style="font-family:courier new,monospace">
const Derived& self() const { return
*static_cast<const Derived*>(this); }<br>
</span></span><span style="font-family:courier
new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace">
Derived& self() { return
*static_cast<Derived*>(this); }<br>
</span></span></span></b></span></span></span>
public:<br>
T& operator *() const { return *<b>self()</b>.get();
}<br>
// etc.<br>
</span></span><span style="font-family:courier
new,monospace"><span style="font-family:courier
new,monospace"> <b>}</b>;<br>
<b>};<br>
</b></span></span></span></span></span></span>
<div><br>
So that you can use self() directly.<br>
</div>
<blockquote
cite="mid:15667a97-e6f3-46fb-b346-6f248b5815cf@isocpp.org"
type="cite">
<div dir="ltr">
<div>You could define the macro to expand to something like</div>
<div><br>
</div>
<div>class NAME {</div>
<div> template <typename Derived, typename Base> class
type;</div>
<div>};</div>
<div>template <typename Derived, typename Base> class
NAME::type /* user continues here */</div>
<div><br>
</div>
<div>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.</div>
<div><br>
</div>
<div> </div>
<blockquote class="gmail_quote" style="margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor="#FFFFFF" text="#000000"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><span
style="font-family:courier new,monospace"><b> <br>
</b>This approach solve some of the drawbacks
you mention, while not all. <br>
</span></span></span></span></span></span></div>
</blockquote>
<div><br>
</div>
<div>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.</div>
</div>
</blockquote>
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.
<blockquote
cite="mid:15667a97-e6f3-46fb-b346-6f248b5815cf@isocpp.org"
type="cite">
<div dir="ltr">
<div> </div>
<blockquote class="gmail_quote" style="margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor="#FFFFFF" text="#000000"> Does making mixins act
like data member makes then increase the size of the class?<br>
Have you considered to see them as part of the inheritance
hierarchy?<br>
</div>
</blockquote>
<div><br>
</div>
<div>Mixins don't act like data members for any purpose but
construction/destruction.</div>
</div>
</blockquote>
OK.<br>
<blockquote
cite="mid:15667a97-e6f3-46fb-b346-6f248b5815cf@isocpp.org"
type="cite">
<div dir="ltr">
<div> </div>
<blockquote class="gmail_quote" style="margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor="#FFFFFF" text="#000000"> <br>
<span style="font-family:courier new,monospace">class foo :
public mixin X <br>
{<br>
};</span></div>
</blockquote>
<div><br>
</div>
<div>This runs into the problems I mentioned about the
completeness of foo within the mixin.</div>
</div>
</blockquote>
I don't see this as a problem, but a future of mixins. A mixin has
only sense once instantiated.<br>
<blockquote
cite="mid:15667a97-e6f3-46fb-b346-6f248b5815cf@isocpp.org"
type="cite">
<div dir="ltr">
<div> </div>
<blockquote class="gmail_quote" style="margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor="#FFFFFF" text="#000000">
<blockquote type="cite">
<div dir="ltr"> Since the mixin is a template, the type of
its 'this' pointer is dependent.<br>
The syntax for acessing members is the same as that for
access to members of<br>
dependent base classes: use 'this->' to make the
expression dependent and delay<br>
lookup until instantiation time.<br>
</div>
</blockquote>
Have you considered adding a self keyword instead of using
this?<br>
</div>
</blockquote>
<div><br>
</div>
<div>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.</div>
</div>
</blockquote>
The keyword can be contextual.<br>
<blockquote
cite="mid:15667a97-e6f3-46fb-b346-6f248b5815cf@isocpp.org"
type="cite">
<div dir="ltr">
<div> </div>
<blockquote class="gmail_quote" style="margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor="#FFFFFF" text="#000000">
<blockquote type="cite">
<div dir="ltr"><br>
Mixins can contain every kind of declaration that
classes can, including inner<br>
types, data members, and more mixin directives. Mixins
cannot have base classes.<br>
(POD: Should they be able to? The bases could be
appended to the list of bases<br>
of the embedding class. What kind of problems could that
cause?)<br>
</div>
</blockquote>
<br>
I don't see why the introduction of the last constraint is
needed. With the CRTP model there is no such limitation<br>
</div>
</blockquote>
<div><br>
</div>
<div>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.</div>
</div>
</blockquote>
Ok.<br>
<blockquote
cite="mid:15667a97-e6f3-46fb-b346-6f248b5815cf@isocpp.org"
type="cite">
<div dir="ltr">
<div> </div>
<blockquote class="gmail_quote" style="margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor="#FFFFFF" text="#000000">
<blockquote type="cite">
<div dir="ltr">- Functions overload. If they cannot
overload, it's an error.<br>
</div>
</blockquote>
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.<br>
<br>
For example, several mixins could define a trace function
that use the base one and add something else<br>
<br>
void trace() {<br>
this->base_type.trace();<br>
// ....<br>
}<br>
</div>
</blockquote>
<div><br>
</div>
<div>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.</div>
</div>
</blockquote>
The alternative CRTP model would allow it without any trouble.<br>
<blockquote
cite="mid:15667a97-e6f3-46fb-b346-6f248b5815cf@isocpp.org"
type="cite">
<div dir="ltr">
<div> </div>
<blockquote class="gmail_quote" style="margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor="#FFFFFF" text="#000000">
<blockquote type="cite">
<div dir="ltr">In addition, it might be useful to make it
possible for mixins to have sections<br>
that are not made visible to the embedding class (e.g. a
"mixin:" access<br>
specifier), although I am hesitant to really do this,
because I can see a<br>
pattern developing where the entire class body is always
put in a mixin, and a<br>
mixin: specifier is used to create "truly hidden"
private sections.<br>
</div>
</blockquote>
Why using private as for class is not enough? What am I
missing?<br>
</div>
</blockquote>
<div><br>
</div>
<div>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.
<br>
</div>
</div>
</blockquote>
Sorry, I don't understand. Are you telling inheriting from multiple
bases?<br>
<br>
Best,<br>
Vicente<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/</a>.<br />
--------------070207030006060406090300--
.
Author: cornedbee@google.com
Date: Tue, 3 Sep 2013 08:54:40 -0700 (PDT)
Raw View
------=_Part_179_31627642.1378223680829
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On Monday, September 2, 2013 7:22:37 PM UTC+2, Vicente J. Botet Escriba=20
wrote:
>
> Le 02/09/13 16:51, corn...@google.com <javascript:> a =E9crit :
> =20
> Nested templates are simply ugly, and that's without trying to define som=
e=20
> of the mixin's methods out-of-line; then you get to multiple template=20
> parameter lists, which I bet 90% of C++ programmers have never seen in=20
> 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=
=20
be impossible for mixins?
=20
> =20
>> class foo : public mixin X=20
>> {
>> };
>>
>
> This runs into the problems I mentioned about the completeness of foo=20
> within the mixin.
> =20
> I don't see this as a problem, but a future of mixins. A mixin has only=
=20
> sense once instantiated.
>
I don't understand what you mean by that. I want mixins to be able to refer=
=20
to at least some members of the embedding class from the mixin body, not=20
just the functions.
=20
> Have you considered adding a self keyword instead of using this?
>> =20
>
> For a moment, but I don't see the point. 'self' is completely impossible=
=20
> to add, since it is widely used as a variable/function name, and the new=
=20
> use would be in a context where a variable name can appear. If you know a=
ny=20
> other conveniently short and logical words that aren't already in wide us=
e=20
> in expression context, I'd love to hear about them, though.
> =20
> The keyword can be contextual.
>
No, it can't be. That's what I've been trying to say with "would be in a=20
context where a variable name can appear". Contextual keywords only work if=
=20
the new use for the keyword is in a context where no existing identifier=20
could appear. For example, the 'final' and 'override' contextual keywords=
=20
only appear after the class name of a class declaration and after the=20
parameter list of a member function; places where neither type names nor=20
variable/function names are allowed. This allows them to be contextual=20
keywords. A 'self' keyword would have to appear in expression context, in=
=20
the place where e.g. 'this' can appear as well. More importantly, a=20
variable named 'self' can appear in this place, and that's why 'self'=20
doesn't work as a contextual keyword.
=20
> This is a good point. Relaying calls from one mixin to another is a use=
=20
> case I haven't considered so far. I have no good solution for this at the=
=20
> moment.
> =20
> The alternative CRTP model would allow it without any trouble.
>
A "rewrite to base classes" semantic model would work for many use cases,=
=20
but not for the class member access I want. Also, initialization order=20
would get interesting, and dealing with multiple mixins implementing=20
functions from each other or multiple pre-existing base classes would bring=
=20
lots of complexity in the definition and the explanation of the feature.=20
Motivating example:
struct Foo { virtual void foo() =3D 0; };
struct Bar { virtual void bar() =3D 0; };
mixin FooImpl {
virtual void baz() =3D 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=20
hierarchy look like?
In the base class model, conflicting names just hide each other; they are=
=20
> not by themselves an error. But going with the model of inheriting=20
> conflicting names from multiple bases might be the best model for what I=
=20
> want to achieve after all.=20
> =20
> Sorry, I don't understand. Are you telling inheriting from multiple bases=
?
>
>
Yes. Think about what happens when you inherit from multiple classes that=
=20
have members with the same name. I think those are the best semantics for=
=20
mixins with conflicting names too.
=20
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_179_31627642.1378223680829
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Monday, September 2, 2013 7:22:37 PM UTC+2, Vic=
ente J. Botet Escriba wrote:<blockquote class=3D"gmail_quote" style=3D"marg=
in: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 02/09/13 16:51, <a href=3D"javascript:" target=3D"_blank" gdf-o=
bfuscated-mailto=3D"08L8DZyS69wJ">corn...@google.com</a>
a =E9crit :<br>
</div>
<blockquote type=3D"cite">
<div dir=3D"ltr">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.<br></div></blockquote>
Why would you need to define the mixin's methods out-of-line?</div></bl=
ockquote><div><br></div><div>Every other construct in C++ allows out-of-lin=
e definition; why should it be impossible for mixins?</div><div>  =
;</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.=
8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF=
" text=3D"#000000"><blockquote type=3D"cite"><div dir=3D"ltr">
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex">
<div bgcolor=3D"#FFFFFF" text=3D"#000000"> <br>
<span style=3D"font-family:courier new,monospace">class foo :
public mixin X <br>
{<br>
};</span></div>
</blockquote>
<div><br>
</div>
<div>This runs into the problems I mentioned about the
completeness of foo within the mixin.</div>
</div>
</blockquote>
I don't see this as a problem, but a future of mixins. A mixin has
only sense once instantiated.<br></div></blockquote><div><br></div><div=
>I don't understand what you mean by that. I want mixins to be able to refe=
r to at least some members of the embedding class from the mixin body, not =
just the functions.</div><div> </div><blockquote class=3D"gmail_quote"=
style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-=
left: 1ex;"><div bgcolor=3D"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div bgcolor=3D"#FFFFFF" te=
xt=3D"#000000">Have you considered adding a self keyword instead of using
this?<br>
</div>
</blockquote>
<div><br>
</div>
<div>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.</div>
</div>
</blockquote>
The keyword can be contextual.<br></div></blockquote><div><br></div><di=
v>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 c=
ould appear. For example, the 'final' and 'override' contextual keywords on=
ly appear after the class name of a class declaration and after the paramet=
er 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 wher=
e 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 contextu=
al keyword.</div><div> </div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div bgcolor=3D"#FFFFFF" text=3D"#000000"><blockquote type=3D"cite"><=
div dir=3D"ltr">
<div>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.</div>
</div>
</blockquote>
The alternative CRTP model would allow it without any trouble.<br></div=
></blockquote><div><br></div><div>A "rewrite to base classes" semantic mode=
l would work for many use cases, but not for the class member access I want=
.. Also, initialization order would get interesting, and dealing with multip=
le mixins implementing functions from each other or multiple pre-existing b=
ase classes would bring lots of complexity in the definition and the explan=
ation of the feature. Motivating example:</div><div><br></div><div><font fa=
ce=3D"courier new, monospace">struct Foo { virtual void foo() =3D 0; };</fo=
nt></div><div><font face=3D"courier new, monospace">struct Bar { virtual vo=
id bar() =3D 0; };</font></div><div><font face=3D"courier new, monospace">m=
ixin FooImpl {</font></div><div><font face=3D"courier new, monospace"> =
; virtual void baz() =3D 0;</font></div><div><font face=3D"courier new, mon=
ospace"> void foo() { baz(); }</font></div><div><font face=3D"courier=
new, monospace">}</font></div><div><font face=3D"courier new, monospace">m=
ixin BarBazImpl {</font></div><div><font face=3D"courier new, monospace">&n=
bsp; void bar() {}</font></div><div><font face=3D"courier new, monospace">&=
nbsp; void baz() {}</font></div><div><font face=3D"courier new, monospace">=
}</font></div><div><font face=3D"courier new, monospace">struct FooBar : Fo=
o, Bar, mixin FooImpl, mixin BarBazImpl {};</font></div><div><br></div><div=
>Is the order of the mixins important here? What would the rewritten hierar=
chy look like?</div><div><br></div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div bgcolor=3D"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div>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.&nbs=
p;<br></div>
</div>
</blockquote>
Sorry, I don't understand. Are you telling inheriting from multiple
bases?<br><br></div></blockquote><div><br></div><div>Yes. Think about w=
hat happens when you inherit from multiple classes that have members with t=
he same name. I think those are the best semantics for mixins with conflict=
ing names too.</div><div> </div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_179_31627642.1378223680829--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Sat, 19 Jul 2014 16:12:37 +0200
Raw View
This is a multi-part message in MIME format.
--------------090004030703080301080604
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 03/09/13 17:54, cornedbee@google.com a =E9crit :
While doing some search about mixins I have found that I didn't replied=20
to this post :(
Hoping this is not too late ;-)
>
> On Monday, September 2, 2013 7:22:37 PM UTC+2, Vicente J. Botet=20
> Escriba wrote:
>
> Le 02/09/13 16:51, corn...@google.com <javascript:> a =E9crit :
>> 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=20
> it be impossible for mixins?
I have not said that it is impossible. You said that it was just even=20
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=20
> 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=20
> a context where a variable name can appear". Contextual keywords only=20
> work if the new use for the keyword is in a context where no existing=20
> identifier could appear. For example, the 'final' and 'override'=20
> contextual keywords only appear after the class name of a class=20
> declaration and after the parameter list of a member function; places=20
> where neither type names nor variable/function names are allowed. This=20
> allows them to be contextual keywords. A 'self' keyword would have to=20
> appear in expression context, in the place where e.g. 'this' can=20
> appear as well. More importantly, a variable named 'self' can appear=20
> 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=20
the embedding class.
On the Stack approach mixins can make use either of something under the=20
stack and we use
this->base_type.member
or something on top of the stack, visible from the embedding class and=20
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=20
> cases, but not for the class member access I want. Also,=20
> initialization order would get interesting, and dealing with multiple=20
> mixins implementing functions from each other or multiple pre-existing=20
> base classes would bring lots of complexity in the definition and the=20
> explanation of the feature.
I agree that your base class model is simpler and easier to understand,=20
but less powerfully as the contribution of each mixin is exclusive, and=20
you can not support each mixing participating on a chain of=20
responsibility, as e.g. the trace() function I showed before.
> Motivating example:
>
> struct Foo { virtual void foo() =3D 0; };
> struct Bar { virtual void bar() =3D 0; };
> mixin FooImpl {
> virtual void baz() =3D 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=20
> hierarchy look like?
The mixins can have multiple base classes. let me use=20
__multiple<__pub<X>, __pric<Y> to mean a mixin class inherits publicly=20
from X and privately from Y.
The CRTP model would something like
struct FooBar : BarBazImpl<FooBar, FooImpl<FooBar, __multiple<=20
__pub<Foo>, __pub<Bar>>>> {};
or
struct FooBar : mixins< __multiple< __pub<Foo>, __pub<Bar>>, FooImpl,=20
BarBazImpl> {};
The main problem with this approach is the construction of the mixins=20
using direct C++. But I could hope that a compiler could do the expected=20
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=20
> that have members with the same name. I think those are the best=20
> semantics for mixins with conflicting names too.
>
I could agree the conflict arise for non-private data members, but it=20
should not arise for private ones and functions members.
Note again that I'm not against a mixin feature, but IMHO the flat model=20
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
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------090004030703080301080604
Content-Type: text/html; charset=ISO-8859-1
<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div class="moz-cite-prefix">Le 03/09/13 17:54, <a
class="moz-txt-link-abbreviated"
href="mailto:cornedbee@google.com">cornedbee@google.com</a> a
écrit :<br>
</div>
<br>
While doing some search about mixins I have found that I didn't
replied to this post :(<br>
Hoping this is not too late ;-)<br>
<blockquote
cite="mid:d3a05748-2235-44e5-9b25-6d7310d8536d@isocpp.org"
type="cite">
<div dir="ltr"> <br>
On Monday, September 2, 2013 7:22:37 PM UTC+2, Vicente J. Botet
Escriba wrote:
<blockquote class="gmail_quote" style="margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor="#FFFFFF" text="#000000">
<div>Le 02/09/13 16:51, <a moz-do-not-send="true"
href="javascript:" target="_blank"
gdf-obfuscated-mailto="08L8DZyS69wJ">corn...@google.com</a>
a écrit :<br>
</div>
<blockquote type="cite">
<div dir="ltr">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.<br>
</div>
</blockquote>
Why would you need to define the mixin's methods
out-of-line?</div>
</blockquote>
<div><br>
</div>
<div>Every other construct in C++ allows out-of-line definition;
why should it be impossible for mixins?</div>
</div>
</blockquote>
I have not said that it is impossible. You said that it was just
even uglier.<br>
<blockquote
cite="mid:d3a05748-2235-44e5-9b25-6d7310d8536d@isocpp.org"
type="cite">
<div dir="ltr">
<div> </div>
<blockquote class="gmail_quote" style="margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor="#FFFFFF" text="#000000">
<blockquote type="cite">
<div dir="ltr">
<blockquote class="gmail_quote"
style="margin:0;margin-left:0.8ex;border-left:1px #ccc
solid;padding-left:1ex">
<div bgcolor="#FFFFFF" text="#000000"> <br>
<span style="font-family:courier new,monospace">class
foo : public mixin X <br>
{<br>
};</span></div>
</blockquote>
<div><br>
</div>
<div>This runs into the problems I mentioned about the
completeness of foo within the mixin.</div>
</div>
</blockquote>
I don't see this as a problem, but a future of mixins. A
mixin has only sense once instantiated.<br>
</div>
</blockquote>
<div><br>
</div>
<div>I don't understand what you mean by that. </div>
</div>
</blockquote>
I meant a feature of mixins, not a future.<br>
<blockquote
cite="mid:d3a05748-2235-44e5-9b25-6d7310d8536d@isocpp.org"
type="cite">
<div dir="ltr">
<div>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.</div>
</div>
</blockquote>
Me too. We agree here.<br>
<blockquote
cite="mid:d3a05748-2235-44e5-9b25-6d7310d8536d@isocpp.org"
type="cite">
<div dir="ltr">
<div> </div>
<blockquote class="gmail_quote" style="margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor="#FFFFFF" text="#000000">
<blockquote type="cite">
<div dir="ltr">
<blockquote class="gmail_quote"
style="margin:0;margin-left:0.8ex;border-left:1px #ccc
solid;padding-left:1ex">
<div bgcolor="#FFFFFF" text="#000000">Have you
considered adding a self keyword instead of using
this?<br>
</div>
</blockquote>
<div><br>
</div>
<div>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.</div>
</div>
</blockquote>
The keyword can be contextual.<br>
</div>
</blockquote>
<div><br>
</div>
<div>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.</div>
</div>
</blockquote>
You are right it can not be contextual. <br>
<br>
On the Flat approach mixins can make use only of members visible
from the embedding class.<br>
<br>
On the Stack approach mixins can make use either of something under
the stack and we use<br>
<br>
this->base_type.member<br>
<br>
or something on top of the stack, visible from the embedding class
and we use<br>
<br>
self().member<br>
<br>
<br>
<br>
<br>
<blockquote
cite="mid:d3a05748-2235-44e5-9b25-6d7310d8536d@isocpp.org"
type="cite">
<div dir="ltr">
<div> </div>
<blockquote class="gmail_quote" style="margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor="#FFFFFF" text="#000000">
<blockquote type="cite">
<div dir="ltr">
<div>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.</div>
</div>
</blockquote>
The alternative CRTP model would allow it without any
trouble.<br>
</div>
</blockquote>
<div><br>
</div>
<div>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.</div>
</div>
</blockquote>
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.<br>
<blockquote
cite="mid:d3a05748-2235-44e5-9b25-6d7310d8536d@isocpp.org"
type="cite">
<div dir="ltr">
<div> Motivating example:</div>
<div><br>
</div>
<div><font face="courier new, monospace">struct Foo { virtual
void foo() = 0; };</font></div>
<div><font face="courier new, monospace">struct Bar { virtual
void bar() = 0; };</font></div>
<div><font face="courier new, monospace">mixin FooImpl {</font></div>
<div><font face="courier new, monospace"> virtual void baz() =
0;</font></div>
<div><font face="courier new, monospace"> void foo() { baz(); }</font></div>
<div><font face="courier new, monospace">}</font></div>
<div><font face="courier new, monospace">mixin BarBazImpl {</font></div>
<div><font face="courier new, monospace"> void bar() {}</font></div>
<div><font face="courier new, monospace"> void baz() {}</font></div>
<div><font face="courier new, monospace">}</font></div>
<div><font face="courier new, monospace">struct FooBar : Foo,
Bar, mixin FooImpl, mixin BarBazImpl {};</font></div>
</div>
</blockquote>
<blockquote
cite="mid:d3a05748-2235-44e5-9b25-6d7310d8536d@isocpp.org"
type="cite">
<div dir="ltr">
<div><br>
</div>
<div>Is the order of the mixins important here? What would the
rewritten hierarchy look like?</div>
</div>
</blockquote>
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.<br>
The CRTP model would something like<br>
<br>
struct FooBar : BarBazImpl<FooBar, FooImpl<FooBar,
__multiple< __pub<Foo>, __pub<Bar>>>> {};<br>
<br>
or <br>
<br>
struct FooBar : mixins< __multiple< __pub<Foo>,
__pub<Bar>>, FooImpl, BarBazImpl> {};<br>
<br>
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 <font
face="courier new, monospace">FooImpl and last </font><font
face="courier new, monospace">BarBazImpl.</font><br>
<br>
<blockquote
cite="mid:d3a05748-2235-44e5-9b25-6d7310d8536d@isocpp.org"
type="cite">
<div dir="ltr">
<div><br>
</div>
<blockquote class="gmail_quote" style="margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor="#FFFFFF" text="#000000">
<blockquote type="cite">
<div dir="ltr">
<div>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. <br>
</div>
</div>
</blockquote>
Sorry, I don't understand. Are you telling inheriting from
multiple bases?<br>
<br>
</div>
</blockquote>
<div><br>
</div>
<div>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.</div>
<div> </div>
</div>
<br>
</blockquote>
I could agree the conflict arise for non-private data members, but
it should not arise for private ones and functions members.<br>
<br>
Note again that I'm not against a mixin feature, but IMHO the flat
model could be improved with a stack of mixins.<br>
<br>
I could be for any syntaxes if what is behind is a stack of mixins,
either<br>
<br>
<div><font face="courier new, monospace">struct FooBar : Foo, Bar,
mixin FooImpl, mixin BarBazImpl {};<br>
<br>
or <br>
<br>
</font>
<div><font face="courier new, monospace">struct FooBar : Foo, Bar
{<br>
</font><font face="courier new, monospace"><font face="courier
new, monospace"> using mixin FooImpl;<br>
using mixin BarBazImpl;<br>
</font>};</font></div>
<br>
</div>
<br>
Best,<br>
Vicente<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="mailto:std-proposals+unsubscribe@isocpp.org">std-proposals+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href="mailto:std-proposals@isocpp.org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/</a>.<br />
--------------090004030703080301080604--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Tue, 22 Jul 2014 07:37:51 +0200
Raw View
This is a multi-part message in MIME format.
--------------050109040003050904070008
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 28/08/13 01:43, Sebastian Redl a =E9crit :
>
>
> On Wednesday, August 28, 2013 12:50:14 AM UTC+2, Klaim - Jo=EBl Lamotte=
=20
> 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=20
> current access specifiers. But my worry goes beyond just access and=20
> concerns visibility:
>
> template <typename T>
> mixin Foo {
> using my_secret_helper_type =3D complicated_metaprogram<T>;
> // how do I keep my_secret_helper_type from colliding with types in=20
> embedding classes?
> // I can't open a namespace here, but I don't want to start with=20
> prefixes again
>
> mixin:
> using this_can_never_conflict =3D other_metaprogram<T>;
> // awesome, I can use these without worries, because they're truly=20
> local to this class
> }
>
> I see these options to solve this problem:
> 1) Do nothing. Have the users use prefixes. This seems extremely=20
> inelegant to me.
> 1a) Merge what can be merged, but otherwise error out, as I described=20
> in my original post. Marginally better than 1).
> 2) Have declarations in the embedding class shadow those in mixins.=20
> Except for overloads maybe? But what if two mixins conflict? Earlier=20
> shadows later? Later shadows earlier? Declarations co-exist but are=20
> ambiguous when accessed?
> 2a) Embedding class shadows mixins, functions don't overload, multiple=20
> mixins coexist and are ambiguous in access. This is the "let's pretend=20
> we're still mixing in CRTP base classes" model. But given that I want=20
> 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=20
> their implementation details, and have other conflicting parts=20
> generate an error. Sounds reasonable, except that, as I said, this=20
> would mean that mixins provide a feature that C++ doesn't otherwise=20
> have, and I'm worried that they'll be used for that feature alone,=20
> leading to obfuscated code. But maybe I shouldn't be worried about=20
> that. I can still worry about implementability, though.
> 3a) Combine 3) with the merging from 1a) for non-hidden things. I like=20
> this merging - it feels intuitive and right. But maybe that's just=20
> because of where I'm coming from.
>
>
I think that mixins should follows the same rules as if they were=20
derived classes. In addition, I believe that mixins are syntactic sugar=20
of the CRTP idiom and that its semantics should be defined as a=20
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=20
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=20
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=20
the mixin members using the mixin name and can shadow the conflicting=20
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=20
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 =3D 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
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------050109040003050904070008
Content-Type: text/html; charset=ISO-8859-1
<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div class="moz-cite-prefix">Le 28/08/13 01:43, Sebastian Redl a
écrit :<br>
</div>
<blockquote
cite="mid:8344e51d-d912-4bd9-add3-233f4b0370bf@isocpp.org"
type="cite">
<div dir="ltr"><br>
<br>
On Wednesday, August 28, 2013 12:50:14 AM UTC+2, Klaim - Joël
Lamotte wrote:<br>
<div><br>
</div>
<blockquote class="gmail_quote" style="margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div dir="ltr">
<div>
<div>3. <br>
<br>
<div>Now if mixins have accessors inside, there seem to
be several ways possibilities:<br>
</div>
</div>
</div>
</div>
</blockquote>
<div><br>
You have pretty much enumerated the access possibilities given
the current access specifiers. But my worry goes beyond just
access and concerns visibility:<br>
<br>
template <typename T><br>
mixin Foo {<br>
using my_secret_helper_type =
complicated_metaprogram<T>;<br>
// how do I keep my_secret_helper_type from colliding with
types in embedding classes?<br>
// I can't open a namespace here, but I don't want to start
with prefixes again<br>
<br>
mixin:<br>
using this_can_never_conflict = other_metaprogram<T>;<br>
// awesome, I can use these without worries, because they're
truly local to this class<br>
}<br>
<br>
I see these options to solve this problem:<br>
1) Do nothing. Have the users use prefixes. This seems
extremely inelegant to me.<br>
1a) Merge what can be merged, but otherwise error out, as I
described in my original post. Marginally better than 1).<br>
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?<br>
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.<br>
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.<br>
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.<br>
<br>
</div>
<blockquote class="gmail_quote" style="margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"> </blockquote>
</div>
<br>
</blockquote>
<br>
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.<br>
<br>
Next follow the rules I find more convenient. <br>
<br>
* Declarations on the embedding class/mixin shadows those in the
used mixins.<br>
<br>
mixin A { void f(); }<br>
class C { <br>
public:<br>
using mixin A;<br>
void f() // shadows A::f()<br>
{<br>
// ...<br>
}<br>
};<br>
<br>
The class C has access to the shadowed members using the mixin name<br>
<br>
class C { <br>
public:<br>
using mixin A;<br>
void f() // shadows A::f()<br>
{<br>
A::f(); // but the shadowed member can be accessed qualified<br>
// do more ...<br>
}<br>
};<br>
<br>
<br>
* The using mixin directive make visible only the symbols that are
not ambiguous and not shadowed. There is no precedence between
mixins.<br>
<br>
mixin A { void f(); void g(); }<br>
mixin B { void f(); void h();}<br>
class C { <br>
public:<br>
using mixin A;<br>
using mixin B;<br>
// f is ambiguous, g and h are visible<br>
void x() <br>
{<br>
// this->f(); // error f is ambiguous<br>
this->g();<br>
this->h();<br>
// ...<br>
}<br>
};<br>
<br>
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.<br>
<br>
class C { <br>
public:<br>
using mixin A;<br>
using mixin B;<br>
void f() <br>
{<br>
this->A::f();<br>
this->B::f();<br>
// ...<br>
}<br>
};<br>
<br>
Mixins can also use others mixins, so that a stack of mixins can be
constructed and the mixin can be template parameters<br>
<br>
template <mixin M><br>
mixin X {<br>
using mixin M;<br>
void trace() {<br>
this->M::trace();<br>
// ...<br>
}<br>
};<br>
<br>
mixin A { void trace();...}<br>
<br>
class C {<br>
using mixin T = X<A>; // use of alias to simplify the use of
the mixin<br>
void trace() {<br>
this->T::trace();<br>
// ...<br>
}<br>
};<br>
<br>
* Mixins names can also be part of the class interface, <br>
<br>
mixin A { void f(); void g(); }<br>
mixin B { void f(); void h();}<br>
class C { <br>
private:<br>
using mixin A;<br>
public:<br>
using mixin B;<br>
void f() <br>
{<br>
this->A::f();<br>
this->B::f();<br>
// ...<br>
}<br>
};<br>
<br>
C c;<br>
c.f(); // OK<br>
c.g(); // ERROR<br>
c.h(); // OK<br>
c.A::f(); // ERROR<br>
c.A::g(); // ERROR<br>
c.B::f(); // OK<br>
c.B::h(); // OK<br>
<br>
<br>
Vicente<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="mailto:std-proposals+unsubscribe@isocpp.org">std-proposals+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href="mailto:std-proposals@isocpp.org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/</a>.<br />
--------------050109040003050904070008--
.
Author: Roland Bock <rbock@eudoxos.de>
Date: Thu, 24 Jul 2014 12:10:14 +0200
Raw View
This is a multi-part message in MIME format.
--------------020705060503030508080601
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On 2014-07-22 07:37, Vicente J. Botet Escriba wrote:
> Le 28/08/13 01:43, Sebastian Redl a =E9crit :
>>
>>
>> On Wednesday, August 28, 2013 12:50:14 AM UTC+2, Klaim - Jo=EBl Lamotte
>> wrote:
>>
>> =20
>>
>> 3.=20
>>
>> 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 =3D 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 =3D 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()=20
> {
> // 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()=20
> {
> 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 =3D X<A>; // use of alias to simplify the use of the mixi=
n
> void trace() {
> this->T::trace();
> // ...
> }
> };
>
> * Mixins names can also be part of the class interface, =20
>
> mixin A { void f(); void g(); }
> mixin B { void f(); void h();}
> class C {
> private:
> using mixin A;
> public:
> using mixin B;
> void f()=20
> {
> 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
> --=20
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
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------020705060503030508080601
Content-Type: text/html; charset=ISO-8859-1
<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
</head>
<body text="#000000" bgcolor="#FFFFFF">
<div class="moz-cite-prefix">On 2014-07-22 07:37, Vicente J. Botet
Escriba wrote:<br>
</div>
<blockquote cite="mid:53CDF8AF.5050400@wanadoo.fr" type="cite">
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
<div class="moz-cite-prefix">Le 28/08/13 01:43, Sebastian Redl a
écrit :<br>
</div>
<blockquote
cite="mid:8344e51d-d912-4bd9-add3-233f4b0370bf@isocpp.org"
type="cite">
<div dir="ltr"><br>
<br>
On Wednesday, August 28, 2013 12:50:14 AM UTC+2, Klaim - Joël
Lamotte wrote:<br>
<div><br>
</div>
<blockquote class="gmail_quote" style="margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div dir="ltr">
<div>
<div>3. <br>
<br>
<div>Now if mixins have accessors inside, there seem
to be several ways possibilities:<br>
</div>
</div>
</div>
</div>
</blockquote>
<div><br>
You have pretty much enumerated the access possibilities
given the current access specifiers. But my worry goes
beyond just access and concerns visibility:<br>
<br>
template <typename T><br>
mixin Foo {<br>
using my_secret_helper_type =
complicated_metaprogram<T>;<br>
// how do I keep my_secret_helper_type from colliding with
types in embedding classes?<br>
// I can't open a namespace here, but I don't want to
start with prefixes again<br>
<br>
mixin:<br>
using this_can_never_conflict =
other_metaprogram<T>;<br>
// awesome, I can use these without worries, because
they're truly local to this class<br>
}<br>
<br>
I see these options to solve this problem:<br>
1) Do nothing. Have the users use prefixes. This seems
extremely inelegant to me.<br>
1a) Merge what can be merged, but otherwise error out, as I
described in my original post. Marginally better than 1).<br>
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?<br>
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.<br>
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.<br>
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.<br>
<br>
</div>
<blockquote class="gmail_quote" style="margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"> </blockquote>
</div>
<br>
</blockquote>
<br>
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.<br>
<br>
Next follow the rules I find more convenient. <br>
<br>
* Declarations on the embedding class/mixin shadows those in the
used mixins.<br>
<br>
mixin A { void f(); }<br>
class C { <br>
public:<br>
using mixin A;<br>
void f() // shadows A::f()<br>
{<br>
// ...<br>
}<br>
};<br>
<br>
The class C has access to the shadowed members using the mixin
name<br>
<br>
class C { <br>
public:<br>
using mixin A;<br>
void f() // shadows A::f()<br>
{<br>
A::f(); // but the shadowed member can be accessed qualified<br>
// do more ...<br>
}<br>
};<br>
<br>
<br>
* The using mixin directive make visible only the symbols that are
not ambiguous and not shadowed. There is no precedence between
mixins.<br>
<br>
mixin A { void f(); void g(); }<br>
mixin B { void f(); void h();}<br>
class C { <br>
public:<br>
using mixin A;<br>
using mixin B;<br>
// f is ambiguous, g and h are visible<br>
void x() <br>
{<br>
// this->f(); // error f is ambiguous<br>
this->g();<br>
this->h();<br>
// ...<br>
}<br>
};<br>
<br>
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.<br>
<br>
class C { <br>
public:<br>
using mixin A;<br>
using mixin B;<br>
void f() <br>
{<br>
this->A::f();<br>
this->B::f();<br>
// ...<br>
}<br>
};<br>
<br>
Mixins can also use others mixins, so that a stack of mixins can
be constructed and the mixin can be template parameters<br>
<br>
template <mixin M><br>
mixin X {<br>
using mixin M;<br>
void trace() {<br>
this->M::trace();<br>
// ...<br>
}<br>
};<br>
<br>
mixin A { void trace();...}<br>
<br>
class C {<br>
using mixin T = X<A>; // use of alias to simplify the use
of the mixin<br>
void trace() {<br>
this->T::trace();<br>
// ...<br>
}<br>
};<br>
<br>
* Mixins names can also be part of the class interface, <br>
<br>
mixin A { void f(); void g(); }<br>
mixin B { void f(); void h();}<br>
class C { <br>
private:<br>
using mixin A;<br>
public:<br>
using mixin B;<br>
void f() <br>
{<br>
this->A::f();<br>
this->B::f();<br>
// ...<br>
}<br>
};<br>
<br>
C c;<br>
c.f(); // OK<br>
c.g(); // ERROR<br>
c.h(); // OK<br>
c.A::f(); // ERROR<br>
c.A::g(); // ERROR<br>
c.B::f(); // OK<br>
c.B::h(); // OK<br>
<br>
<br>
Vicente<br>
-- <br>
</blockquote>
Thanks for writing this down. I wanted to write pretty much the same
for a few weeks now and never got to it :-)<br>
<br>
Questions:<br>
<ul>
<li>Would data members be supported as well?<br>
</li>
<li>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)? <br>
</li>
</ul>
<p>For the things I have in mind, I would definitely need both
items.<br>
</p>
<p>Cheers,<br>
</p>
<p>Roland<br>
</p>
<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="mailto:std-proposals+unsubscribe@isocpp.org">std-proposals+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href="mailto:std-proposals@isocpp.org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/</a>.<br />
--------------020705060503030508080601--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Thu, 24 Jul 2014 20:07:39 +0200
Raw View
This is a multi-part message in MIME format.
--------------010500090600000308050203
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 24/07/14 12:10, Roland Bock a =E9crit :
> On 2014-07-22 07:37, Vicente J. Botet Escriba wrote:
>> Le 28/08/13 01:43, Sebastian Redl a =E9crit :
>>>
>>>
>>> On Wednesday, August 28, 2013 12:50:14 AM UTC+2, Klaim - Jo=EBl=20
>>> 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=20
>>> current access specifiers. But my worry goes beyond just access and=20
>>> concerns visibility:
>>>
>>> template <typename T>
>>> mixin Foo {
>>> using my_secret_helper_type =3D complicated_metaprogram<T>;
>>> // how do I keep my_secret_helper_type from colliding with types=20
>>> in embedding classes?
>>> // I can't open a namespace here, but I don't want to start with=20
>>> prefixes again
>>>
>>> mixin:
>>> using this_can_never_conflict =3D other_metaprogram<T>;
>>> // awesome, I can use these without worries, because they're truly=20
>>> local to this class
>>> }
>>>
>>> I see these options to solve this problem:
>>> 1) Do nothing. Have the users use prefixes. This seems extremely=20
>>> inelegant to me.
>>> 1a) Merge what can be merged, but otherwise error out, as I=20
>>> described in my original post. Marginally better than 1).
>>> 2) Have declarations in the embedding class shadow those in mixins.=20
>>> Except for overloads maybe? But what if two mixins conflict? Earlier=20
>>> shadows later? Later shadows earlier? Declarations co-exist but are=20
>>> ambiguous when accessed?
>>> 2a) Embedding class shadows mixins, functions don't overload,=20
>>> multiple mixins coexist and are ambiguous in access. This is the=20
>>> "let's pretend we're still mixing in CRTP base classes" model. But=20
>>> given that I want the model to be "these are put into the class",=20
>>> that's very unintuitive.
>>> 3) Provide mixin: or an equivalent way of allowing mixins to hide=20
>>> their implementation details, and have other conflicting parts=20
>>> generate an error. Sounds reasonable, except that, as I said, this=20
>>> would mean that mixins provide a feature that C++ doesn't otherwise=20
>>> have, and I'm worried that they'll be used for that feature alone,=20
>>> leading to obfuscated code. But maybe I shouldn't be worried about=20
>>> that. I can still worry about implementability, though.
>>> 3a) Combine 3) with the merging from 1a) for non-hidden things. I=20
>>> like this merging - it feels intuitive and right. But maybe that's=20
>>> just because of where I'm coming from.
>>>
>>>
>>
>> I think that mixins should follows the same rules as if they were=20
>> derived classes. In addition, I believe that mixins are syntactic=20
>> sugar of the CRTP idiom and that its semantics should be defined as a=20
>> 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=20
>> 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=20
>> 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=20
>> to the mixin members using the mixin name and can shadow the=20
>> 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=20
>> 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 =3D X<A>; // use of alias to simplify the use of the mix=
in
>> 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
>> --=20
> Thanks for writing this down. I wanted to write pretty much the same=20
> 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=20
its embedding class/mixin. This access rights need to be of course=20
transitive.
>
> *
>
> For the things I have in mind, I would definitely need both items.
>
>
Vicente
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------010500090600000308050203
Content-Type: text/html; charset=ISO-8859-1
<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div class="moz-cite-prefix">Le 24/07/14 12:10, Roland Bock a
écrit :<br>
</div>
<blockquote cite="mid:53D0DB86.3060103@eudoxos.de" type="cite">
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
<div class="moz-cite-prefix">On 2014-07-22 07:37, Vicente J. Botet
Escriba wrote:<br>
</div>
<blockquote cite="mid:53CDF8AF.5050400@wanadoo.fr" type="cite">
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
<div class="moz-cite-prefix">Le 28/08/13 01:43, Sebastian Redl a
écrit :<br>
</div>
<blockquote
cite="mid:8344e51d-d912-4bd9-add3-233f4b0370bf@isocpp.org"
type="cite">
<div dir="ltr"><br>
<br>
On Wednesday, August 28, 2013 12:50:14 AM UTC+2, Klaim -
Joël Lamotte wrote:<br>
<div><br>
</div>
<blockquote class="gmail_quote" style="margin:
0;margin-left: 0.8ex;border-left: 1px #ccc
solid;padding-left: 1ex;">
<div dir="ltr">
<div>
<div>3. <br>
<br>
<div>Now if mixins have accessors inside, there seem
to be several ways possibilities:<br>
</div>
</div>
</div>
</div>
</blockquote>
<div><br>
You have pretty much enumerated the access possibilities
given the current access specifiers. But my worry goes
beyond just access and concerns visibility:<br>
<br>
template <typename T><br>
mixin Foo {<br>
using my_secret_helper_type =
complicated_metaprogram<T>;<br>
// how do I keep my_secret_helper_type from colliding
with types in embedding classes?<br>
// I can't open a namespace here, but I don't want to
start with prefixes again<br>
<br>
mixin:<br>
using this_can_never_conflict =
other_metaprogram<T>;<br>
// awesome, I can use these without worries, because
they're truly local to this class<br>
}<br>
<br>
I see these options to solve this problem:<br>
1) Do nothing. Have the users use prefixes. This seems
extremely inelegant to me.<br>
1a) Merge what can be merged, but otherwise error out, as
I described in my original post. Marginally better than
1).<br>
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?<br>
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.<br>
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.<br>
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.<br>
<br>
</div>
<blockquote class="gmail_quote" style="margin:
0;margin-left: 0.8ex;border-left: 1px #ccc
solid;padding-left: 1ex;"> </blockquote>
</div>
<br>
</blockquote>
<br>
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.<br>
<br>
Next follow the rules I find more convenient. <br>
<br>
* Declarations on the embedding class/mixin shadows those in the
used mixins.<br>
<br>
mixin A { void f(); }<br>
class C { <br>
public:<br>
using mixin A;<br>
void f() // shadows A::f()<br>
{<br>
// ...<br>
}<br>
};<br>
<br>
The class C has access to the shadowed members using the mixin
name<br>
<br>
class C { <br>
public:<br>
using mixin A;<br>
void f() // shadows A::f()<br>
{<br>
A::f(); // but the shadowed member can be accessed qualified<br>
// do more ...<br>
}<br>
};<br>
<br>
<br>
* The using mixin directive make visible only the symbols that
are not ambiguous and not shadowed. There is no precedence
between mixins.<br>
<br>
mixin A { void f(); void g(); }<br>
mixin B { void f(); void h();}<br>
class C { <br>
public:<br>
using mixin A;<br>
using mixin B;<br>
// f is ambiguous, g and h are visible<br>
void x() <br>
{<br>
// this->f(); // error f is ambiguous<br>
this->g();<br>
this->h();<br>
// ...<br>
}<br>
};<br>
<br>
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.<br>
<br>
class C { <br>
public:<br>
using mixin A;<br>
using mixin B;<br>
void f() <br>
{<br>
this->A::f();<br>
this->B::f();<br>
// ...<br>
}<br>
};<br>
<br>
Mixins can also use others mixins, so that a stack of mixins can
be constructed and the mixin can be template parameters<br>
<br>
template <mixin M><br>
mixin X {<br>
using mixin M;<br>
void trace() {<br>
this->M::trace();<br>
// ...<br>
}<br>
};<br>
<br>
mixin A { void trace();...}<br>
<br>
class C {<br>
using mixin T = X<A>; // use of alias to simplify the
use of the mixin<br>
void trace() {<br>
this->T::trace();<br>
// ...<br>
}<br>
};<br>
<br>
* Mixins names can also be part of the class interface, <br>
<br>
mixin A { void f(); void g(); }<br>
mixin B { void f(); void h();}<br>
class C { <br>
private:<br>
using mixin A;<br>
public:<br>
using mixin B;<br>
void f() <br>
{<br>
this->A::f();<br>
this->B::f();<br>
// ...<br>
}<br>
};<br>
<br>
C c;<br>
c.f(); // OK<br>
c.g(); // ERROR<br>
c.h(); // OK<br>
c.A::f(); // ERROR<br>
c.A::g(); // ERROR<br>
c.B::f(); // OK<br>
c.B::h(); // OK<br>
<br>
<br>
Vicente<br>
-- <br>
</blockquote>
Thanks for writing this down. I wanted to write pretty much the
same for a few weeks now and never got to it :-)<br>
<br>
</blockquote>
You are welcome.<br>
<blockquote cite="mid:53D0DB86.3060103@eudoxos.de" type="cite">
Questions:<br>
<ul>
<li>Would data members be supported as well?<br>
</li>
</ul>
</blockquote>
Yes. Types would be supported also.<br>
<blockquote cite="mid:53D0DB86.3060103@eudoxos.de" type="cite"><br>
<ul>
<li>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)? <br>
</li>
</ul>
</blockquote>
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.<br>
<blockquote cite="mid:53D0DB86.3060103@eudoxos.de" type="cite">
<ul>
<li> </li>
</ul>
<p>For the things I have in mind, I would definitely need both
items.<br>
</p>
<br>
</blockquote>
Vicente<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="mailto:std-proposals+unsubscribe@isocpp.org">std-proposals+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href="mailto:std-proposals@isocpp.org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/</a>.<br />
--------------010500090600000308050203--
.
Author: Roland Bock <rbock@eudoxos.de>
Date: Thu, 24 Jul 2014 20:32:42 +0200
Raw View
This is a multi-part message in MIME format.
--------------050807070007060803040600
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On 2014-07-24 20:07, Vicente J. Botet Escriba wrote:
> Le 24/07/14 12:10, Roland Bock a =E9crit :
>> On 2014-07-22 07:37, Vicente J. Botet Escriba wrote:
>>> Le 28/08/13 01:43, Sebastian Redl a =E9crit :
>>>>
>>>>
>>>> On Wednesday, August 28, 2013 12:50:14 AM UTC+2, Klaim - Jo=EBl
>>>> Lamotte wrote:
>>>>
>>>> =20
>>>>
>>>> 3.=20
>>>>
>>>> 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 =3D 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 =3D 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()=20
>>> {
>>> // 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()=20
>>> {
>>> 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 =3D X<A>; // use of alias to simplify the use of the mi=
xin
>>> void trace() {
>>> this->T::trace();
>>> // ...
>>> }
>>> };
>>>
>>> * Mixins names can also be part of the class interface, =20
>>>
>>> mixin A { void f(); void g(); }
>>> mixin B { void f(); void h();}
>>> class C {
>>> private:
>>> using mixin A;
>>> public:
>>> using mixin B;
>>> void f()=20
>>> {
>>> 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
>>> --=20
>> 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?
>>
>> *
>>
>>
>> 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
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------050807070007060803040600
Content-Type: text/html; charset=ISO-8859-1
<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
</head>
<body text="#000000" bgcolor="#FFFFFF">
<div class="moz-cite-prefix">On 2014-07-24 20:07, Vicente J. Botet
Escriba wrote:<br>
</div>
<blockquote cite="mid:53D14B6B.5080202@wanadoo.fr" type="cite">
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
<div class="moz-cite-prefix">Le 24/07/14 12:10, Roland Bock a
écrit :<br>
</div>
<blockquote cite="mid:53D0DB86.3060103@eudoxos.de" type="cite">
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
<div class="moz-cite-prefix">On 2014-07-22 07:37, Vicente J.
Botet Escriba wrote:<br>
</div>
<blockquote cite="mid:53CDF8AF.5050400@wanadoo.fr" type="cite">
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
<div class="moz-cite-prefix">Le 28/08/13 01:43, Sebastian Redl
a écrit :<br>
</div>
<blockquote
cite="mid:8344e51d-d912-4bd9-add3-233f4b0370bf@isocpp.org"
type="cite">
<div dir="ltr"><br>
<br>
On Wednesday, August 28, 2013 12:50:14 AM UTC+2, Klaim -
Joël Lamotte wrote:<br>
<div><br>
</div>
<blockquote class="gmail_quote" style="margin:
0;margin-left: 0.8ex;border-left: 1px #ccc
solid;padding-left: 1ex;">
<div dir="ltr">
<div>
<div>3. <br>
<br>
<div>Now if mixins have accessors inside, there
seem to be several ways possibilities:<br>
</div>
</div>
</div>
</div>
</blockquote>
<div><br>
You have pretty much enumerated the access possibilities
given the current access specifiers. But my worry goes
beyond just access and concerns visibility:<br>
<br>
template <typename T><br>
mixin Foo {<br>
using my_secret_helper_type =
complicated_metaprogram<T>;<br>
// how do I keep my_secret_helper_type from colliding
with types in embedding classes?<br>
// I can't open a namespace here, but I don't want to
start with prefixes again<br>
<br>
mixin:<br>
using this_can_never_conflict =
other_metaprogram<T>;<br>
// awesome, I can use these without worries, because
they're truly local to this class<br>
}<br>
<br>
I see these options to solve this problem:<br>
1) Do nothing. Have the users use prefixes. This seems
extremely inelegant to me.<br>
1a) Merge what can be merged, but otherwise error out,
as I described in my original post. Marginally better
than 1).<br>
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?<br>
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.<br>
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.<br>
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.<br>
<br>
</div>
<blockquote class="gmail_quote" style="margin:
0;margin-left: 0.8ex;border-left: 1px #ccc
solid;padding-left: 1ex;"> </blockquote>
</div>
<br>
</blockquote>
<br>
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.<br>
<br>
Next follow the rules I find more convenient. <br>
<br>
* Declarations on the embedding class/mixin shadows those in
the used mixins.<br>
<br>
mixin A { void f(); }<br>
class C { <br>
public:<br>
using mixin A;<br>
void f() // shadows A::f()<br>
{<br>
// ...<br>
}<br>
};<br>
<br>
The class C has access to the shadowed members using the mixin
name<br>
<br>
class C { <br>
public:<br>
using mixin A;<br>
void f() // shadows A::f()<br>
{<br>
A::f(); // but the shadowed member can be accessed
qualified<br>
// do more ...<br>
}<br>
};<br>
<br>
<br>
* The using mixin directive make visible only the symbols that
are not ambiguous and not shadowed. There is no precedence
between mixins.<br>
<br>
mixin A { void f(); void g(); }<br>
mixin B { void f(); void h();}<br>
class C { <br>
public:<br>
using mixin A;<br>
using mixin B;<br>
// f is ambiguous, g and h are visible<br>
void x() <br>
{<br>
// this->f(); // error f is ambiguous<br>
this->g();<br>
this->h();<br>
// ...<br>
}<br>
};<br>
<br>
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.<br>
<br>
class C { <br>
public:<br>
using mixin A;<br>
using mixin B;<br>
void f() <br>
{<br>
this->A::f();<br>
this->B::f();<br>
// ...<br>
}<br>
};<br>
<br>
Mixins can also use others mixins, so that a stack of mixins
can be constructed and the mixin can be template parameters<br>
<br>
template <mixin M><br>
mixin X {<br>
using mixin M;<br>
void trace() {<br>
this->M::trace();<br>
// ...<br>
}<br>
};<br>
<br>
mixin A { void trace();...}<br>
<br>
class C {<br>
using mixin T = X<A>; // use of alias to simplify the
use of the mixin<br>
void trace() {<br>
this->T::trace();<br>
// ...<br>
}<br>
};<br>
<br>
* Mixins names can also be part of the class interface, <br>
<br>
mixin A { void f(); void g(); }<br>
mixin B { void f(); void h();}<br>
class C { <br>
private:<br>
using mixin A;<br>
public:<br>
using mixin B;<br>
void f() <br>
{<br>
this->A::f();<br>
this->B::f();<br>
// ...<br>
}<br>
};<br>
<br>
C c;<br>
c.f(); // OK<br>
c.g(); // ERROR<br>
c.h(); // OK<br>
c.A::f(); // ERROR<br>
c.A::g(); // ERROR<br>
c.B::f(); // OK<br>
c.B::h(); // OK<br>
<br>
<br>
Vicente<br>
-- <br>
</blockquote>
Thanks for writing this down. I wanted to write pretty much the
same for a few weeks now and never got to it :-)<br>
<br>
</blockquote>
You are welcome.<br>
<blockquote cite="mid:53D0DB86.3060103@eudoxos.de" type="cite">
Questions:<br>
<ul>
<li>Would data members be supported as well?<br>
</li>
</ul>
</blockquote>
Yes. Types would be supported also.<br>
<blockquote cite="mid:53D0DB86.3060103@eudoxos.de" type="cite"><br>
<ul>
<li>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)? <br>
</li>
</ul>
</blockquote>
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.<br>
</blockquote>
Do you have an idea for the syntax of accessing the embedding
class/mixin yet?<br>
<blockquote cite="mid:53D14B6B.5080202@wanadoo.fr" type="cite">
<blockquote cite="mid:53D0DB86.3060103@eudoxos.de" type="cite">
<ul>
<li> <br>
</li>
</ul>
<p>For the things I have in mind, I would definitely need both
items.<br>
</p>
<br>
</blockquote>
<br>
</blockquote>
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?<br>
<br>
<br>
Best regards,<br>
<br>
Roland<br>
<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="mailto:std-proposals+unsubscribe@isocpp.org">std-proposals+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href="mailto:std-proposals@isocpp.org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/</a>.<br />
--------------050807070007060803040600--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Fri, 25 Jul 2014 00:54:08 +0200
Raw View
This is a multi-part message in MIME format.
--------------040705070600030205040304
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 24/07/14 20:32, Roland Bock a =E9crit :
> On 2014-07-24 20:07, Vicente J. Botet Escriba wrote:
>> Le 24/07/14 12:10, Roland Bock a =E9crit :
>>> On 2014-07-22 07:37, Vicente J. Botet Escriba wrote:
>>>> Le 28/08/13 01:43, Sebastian Redl a =E9crit :
>>>>>
>>>>>
>>>>> On Wednesday, August 28, 2013 12:50:14 AM UTC+2, Klaim - Jo=EBl=20
>>>>> 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=20
>>>>> current access specifiers. But my worry goes beyond just access=20
>>>>> and concerns visibility:
>>>>>
>>>>> template <typename T>
>>>>> mixin Foo {
>>>>> using my_secret_helper_type =3D complicated_metaprogram<T>;
>>>>> // how do I keep my_secret_helper_type from colliding with types=20
>>>>> in embedding classes?
>>>>> // I can't open a namespace here, but I don't want to start with=20
>>>>> prefixes again
>>>>>
>>>>> mixin:
>>>>> using this_can_never_conflict =3D other_metaprogram<T>;
>>>>> // awesome, I can use these without worries, because they're=20
>>>>> truly local to this class
>>>>> }
>>>>>
>>>>> I see these options to solve this problem:
>>>>> 1) Do nothing. Have the users use prefixes. This seems extremely=20
>>>>> inelegant to me.
>>>>> 1a) Merge what can be merged, but otherwise error out, as I=20
>>>>> described in my original post. Marginally better than 1).
>>>>> 2) Have declarations in the embedding class shadow those in=20
>>>>> mixins. Except for overloads maybe? But what if two mixins=20
>>>>> conflict? Earlier shadows later? Later shadows earlier?=20
>>>>> Declarations co-exist but are ambiguous when accessed?
>>>>> 2a) Embedding class shadows mixins, functions don't overload,=20
>>>>> multiple mixins coexist and are ambiguous in access. This is the=20
>>>>> "let's pretend we're still mixing in CRTP base classes" model. But=20
>>>>> given that I want the model to be "these are put into the class",=20
>>>>> that's very unintuitive.
>>>>> 3) Provide mixin: or an equivalent way of allowing mixins to hide=20
>>>>> their implementation details, and have other conflicting parts=20
>>>>> generate an error. Sounds reasonable, except that, as I said, this=20
>>>>> would mean that mixins provide a feature that C++ doesn't=20
>>>>> otherwise have, and I'm worried that they'll be used for that=20
>>>>> feature alone, leading to obfuscated code. But maybe I shouldn't=20
>>>>> be worried about that. I can still worry about implementability,=20
>>>>> though.
>>>>> 3a) Combine 3) with the merging from 1a) for non-hidden things. I=20
>>>>> like this merging - it feels intuitive and right. But maybe that's=20
>>>>> just because of where I'm coming from.
>>>>>
>>>>>
>>>>
>>>> I think that mixins should follows the same rules as if they were=20
>>>> derived classes. In addition, I believe that mixins are syntactic=20
>>>> sugar of the CRTP idiom and that its semantics should be defined as=20
>>>> a transformation. I can post it if there is an interest in this=20
>>>> approach.
>>>>
>>>> Next follow the rules I find more convenient.
>>>>
>>>> <>--
>>> Thanks for writing this down. I wanted to write pretty much the same=20
>>> 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=20
>> of its embedding class/mixin. This access rights need to be of course=20
>> transitive.
> Do you have an idea for the syntax of accessing the embedding=20
> 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=20
>> transformation from CRTP. I'd be interested in that transformation.=20
>> 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=20
I have in mind can be transformed to a CRTP implementation. The CRTP=20
implementation can give us the rules we want to emerge and make it=20
possible to prototype it.
Vicente
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------040705070600030205040304
Content-Type: text/html; charset=ISO-8859-1
<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div class="moz-cite-prefix">Le 24/07/14 20:32, Roland Bock a
écrit :<br>
</div>
<blockquote cite="mid:53D1514A.2010008@eudoxos.de" type="cite">
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
<div class="moz-cite-prefix">On 2014-07-24 20:07, Vicente J. Botet
Escriba wrote:<br>
</div>
<blockquote cite="mid:53D14B6B.5080202@wanadoo.fr" type="cite">
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
<div class="moz-cite-prefix">Le 24/07/14 12:10, Roland Bock a
écrit :<br>
</div>
<blockquote cite="mid:53D0DB86.3060103@eudoxos.de" type="cite">
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
<div class="moz-cite-prefix">On 2014-07-22 07:37, Vicente J.
Botet Escriba wrote:<br>
</div>
<blockquote cite="mid:53CDF8AF.5050400@wanadoo.fr" type="cite">
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
<div class="moz-cite-prefix">Le 28/08/13 01:43, Sebastian
Redl a écrit :<br>
</div>
<blockquote
cite="mid:8344e51d-d912-4bd9-add3-233f4b0370bf@isocpp.org"
type="cite">
<div dir="ltr"><br>
<br>
On Wednesday, August 28, 2013 12:50:14 AM UTC+2, Klaim -
Joël Lamotte wrote:<br>
<div><br>
</div>
<blockquote class="gmail_quote" style="margin:
0;margin-left: 0.8ex;border-left: 1px #ccc
solid;padding-left: 1ex;">
<div dir="ltr">
<div>
<div>3. <br>
<br>
<div>Now if mixins have accessors inside, there
seem to be several ways possibilities:<br>
</div>
</div>
</div>
</div>
</blockquote>
<div><br>
You have pretty much enumerated the access
possibilities given the current access specifiers. But
my worry goes beyond just access and concerns
visibility:<br>
<br>
template <typename T><br>
mixin Foo {<br>
using my_secret_helper_type =
complicated_metaprogram<T>;<br>
// how do I keep my_secret_helper_type from
colliding with types in embedding classes?<br>
// I can't open a namespace here, but I don't want
to start with prefixes again<br>
<br>
mixin:<br>
using this_can_never_conflict =
other_metaprogram<T>;<br>
// awesome, I can use these without worries, because
they're truly local to this class<br>
}<br>
<br>
I see these options to solve this problem:<br>
1) Do nothing. Have the users use prefixes. This seems
extremely inelegant to me.<br>
1a) Merge what can be merged, but otherwise error out,
as I described in my original post. Marginally better
than 1).<br>
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?<br>
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.<br>
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.<br>
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.<br>
<br>
</div>
<blockquote class="gmail_quote" style="margin:
0;margin-left: 0.8ex;border-left: 1px #ccc
solid;padding-left: 1ex;"> </blockquote>
</div>
<br>
</blockquote>
<br>
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.<br>
<br>
Next follow the rules I find more convenient. <br>
<br>
<>-- <br>
</blockquote>
Thanks for writing this down. I wanted to write pretty much
the same for a few weeks now and never got to it :-)<br>
<br>
</blockquote>
You are welcome.<br>
<blockquote cite="mid:53D0DB86.3060103@eudoxos.de" type="cite">
Questions:<br>
<ul>
<li>Would data members be supported as well?<br>
</li>
</ul>
</blockquote>
Yes. Types would be supported also.<br>
<blockquote cite="mid:53D0DB86.3060103@eudoxos.de" type="cite"><br>
<ul>
<li>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)? <br>
</li>
</ul>
</blockquote>
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.<br>
</blockquote>
Do you have an idea for the syntax of accessing the embedding
class/mixin yet?<br>
</blockquote>
We could use final to make it explicit <br>
<br>
this->final::member<br>
<br>
<br>
<br>
<blockquote cite="mid:53D1514A.2010008@eudoxos.de" type="cite">
<blockquote cite="mid:53D14B6B.5080202@wanadoo.fr" type="cite">
<blockquote cite="mid:53D0DB86.3060103@eudoxos.de" type="cite">
<ul>
<li> <br>
</li>
</ul>
<p>For the things I have in mind, I would definitely need both
items.<br>
</p>
<br>
</blockquote>
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?<br>
</blockquote>
</blockquote>
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.<br>
<br>
Vicente<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="mailto:std-proposals+unsubscribe@isocpp.org">std-proposals+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href="mailto:std-proposals@isocpp.org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/</a>.<br />
--------------040705070600030205040304--
.
Author: Roland Bock <rbock@eudoxos.de>
Date: Fri, 25 Jul 2014 11:40:04 +0200
Raw View
This is a multi-part message in MIME format.
--------------040206030001060404060909
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On 2014-07-25 00:54, Vicente J. Botet Escriba wrote:
> Le 24/07/14 20:32, Roland Bock a =E9crit :
>> On 2014-07-24 20:07, Vicente J. Botet Escriba wrote:
>>> Le 24/07/14 12:10, Roland Bock a =E9crit :
>>>> On 2014-07-22 07:37, Vicente J. Botet Escriba wrote:
>>>>> Le 28/08/13 01:43, Sebastian Redl a =E9crit :
>>>>>>
>>>>>>
>>>>>> On Wednesday, August 28, 2013 12:50:14 AM UTC+2, Klaim - Jo=EBl
>>>>>> Lamotte wrote:
>>>>>>
>>>>>> =20
>>>>>>
>>>>>> 3.=20
>>>>>>
>>>>>> 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 =3D 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 =3D 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.
>>>>>
>>>>> <>--
>>>> 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.
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
--=20
---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------040206030001060404060909
Content-Type: text/html; charset=ISO-8859-1
<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
</head>
<body text="#000000" bgcolor="#FFFFFF">
<div class="moz-cite-prefix">On 2014-07-25 00:54, Vicente J. Botet
Escriba wrote:<br>
</div>
<blockquote cite="mid:53D18E90.4010901@wanadoo.fr" type="cite">
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
<div class="moz-cite-prefix">Le 24/07/14 20:32, Roland Bock a
écrit :<br>
</div>
<blockquote cite="mid:53D1514A.2010008@eudoxos.de" type="cite">
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
<div class="moz-cite-prefix">On 2014-07-24 20:07, Vicente J.
Botet Escriba wrote:<br>
</div>
<blockquote cite="mid:53D14B6B.5080202@wanadoo.fr" type="cite">
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
<div class="moz-cite-prefix">Le 24/07/14 12:10, Roland Bock a
écrit :<br>
</div>
<blockquote cite="mid:53D0DB86.3060103@eudoxos.de" type="cite">
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
<div class="moz-cite-prefix">On 2014-07-22 07:37, Vicente J.
Botet Escriba wrote:<br>
</div>
<blockquote cite="mid:53CDF8AF.5050400@wanadoo.fr"
type="cite">
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
<div class="moz-cite-prefix">Le 28/08/13 01:43, Sebastian
Redl a écrit :<br>
</div>
<blockquote
cite="mid:8344e51d-d912-4bd9-add3-233f4b0370bf@isocpp.org"
type="cite">
<div dir="ltr"><br>
<br>
On Wednesday, August 28, 2013 12:50:14 AM UTC+2, Klaim
- Joël Lamotte wrote:<br>
<div><br>
</div>
<blockquote class="gmail_quote" style="margin:
0;margin-left: 0.8ex;border-left: 1px #ccc
solid;padding-left: 1ex;">
<div dir="ltr">
<div>
<div>3. <br>
<br>
<div>Now if mixins have accessors inside,
there seem to be several ways possibilities:<br>
</div>
</div>
</div>
</div>
</blockquote>
<div><br>
You have pretty much enumerated the access
possibilities given the current access specifiers.
But my worry goes beyond just access and concerns
visibility:<br>
<br>
template <typename T><br>
mixin Foo {<br>
using my_secret_helper_type =
complicated_metaprogram<T>;<br>
// how do I keep my_secret_helper_type from
colliding with types in embedding classes?<br>
// I can't open a namespace here, but I don't want
to start with prefixes again<br>
<br>
mixin:<br>
using this_can_never_conflict =
other_metaprogram<T>;<br>
// awesome, I can use these without worries,
because they're truly local to this class<br>
}<br>
<br>
I see these options to solve this problem:<br>
1) Do nothing. Have the users use prefixes. This
seems extremely inelegant to me.<br>
1a) Merge what can be merged, but otherwise error
out, as I described in my original post. Marginally
better than 1).<br>
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?<br>
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.<br>
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.<br>
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.<br>
<br>
</div>
<blockquote class="gmail_quote" style="margin:
0;margin-left: 0.8ex;border-left: 1px #ccc
solid;padding-left: 1ex;"> </blockquote>
</div>
<br>
</blockquote>
<br>
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.<br>
<br>
Next follow the rules I find more convenient. <br>
<br>
<>-- <br>
</blockquote>
Thanks for writing this down. I wanted to write pretty much
the same for a few weeks now and never got to it :-)<br>
<br>
</blockquote>
You are welcome.<br>
<blockquote cite="mid:53D0DB86.3060103@eudoxos.de" type="cite">
Questions:<br>
<ul>
<li>Would data members be supported as well?<br>
</li>
</ul>
</blockquote>
Yes. Types would be supported also.<br>
<blockquote cite="mid:53D0DB86.3060103@eudoxos.de" type="cite"><br>
<ul>
<li>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)? <br>
</li>
</ul>
</blockquote>
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.<br>
</blockquote>
Do you have an idea for the syntax of accessing the embedding
class/mixin yet?<br>
</blockquote>
We could use final to make it explicit <br>
<br>
this->final::member<br>
<br>
<br>
<br>
<blockquote cite="mid:53D1514A.2010008@eudoxos.de" type="cite">
<blockquote cite="mid:53D14B6B.5080202@wanadoo.fr" type="cite">
<blockquote cite="mid:53D0DB86.3060103@eudoxos.de" type="cite">
<ul>
<li> <br>
</li>
</ul>
<p>For the things I have in mind, I would definitely need
both items.<br>
</p>
<br>
</blockquote>
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?<br>
</blockquote>
</blockquote>
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.<br>
</blockquote>
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.<br>
<br>
Regards,<br>
<br>
Roland<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="mailto:std-proposals+unsubscribe@isocpp.org">std-proposals+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href="mailto:std-proposals@isocpp.org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/</a>.<br />
--------------040206030001060404060909--
.
Author: Roland Bock <rbock@eudoxos.de>
Date: Thu, 4 Sep 2014 14:49:01 -0700 (PDT)
Raw View
------=_Part_683_336464917.1409867341132
Content-Type: text/plain; charset=UTF-8
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
--
---
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_683_336464917.1409867341132
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Tuesday, August 27, 2013 11:14:41 PM UTC+2, Sebastian R=
edl wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:=
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">The=
ability to inject additional code into a class is something that I have re=
peatedly 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.<br=
><br><br></div></blockquote><div>FYI, I just got confirmation for an open s=
ession at CppCon for this topic:<br><br>http://sched.co/1qh7PQa (Monday eve=
ning)<br><br>I believe to have found a way which is both easier and more po=
werful than what I have seen in this thread. I may be wrong, of course. Loo=
king forward to the discussion. Results will be posted :-)<br><br>Cheers,<b=
r><br>Roland<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_683_336464917.1409867341132--
.
Author: rennnesem@gmail.com
Date: Sun, 1 Feb 2015 12:06:10 -0800 (PST)
Raw View
------=_Part_2068_114959058.1422821170396
Content-Type: multipart/alternative;
boundary="----=_Part_2069_1529089153.1422821170396"
------=_Part_2069_1529089153.1422821170396
Content-Type: text/plain; charset=UTF-8
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
--
---
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2069_1529089153.1422821170396
Content-Type: text/html; charset=UTF-8
<div dir="ltr">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</div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="mailto:std-proposals+unsubscribe@isocpp.org">std-proposals+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href="mailto:std-proposals@isocpp.org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/</a>.<br />
------=_Part_2069_1529089153.1422821170396--
------=_Part_2068_114959058.1422821170396--
.
Author: mobiphil <mobi@mobiphil.com>
Date: Sun, 1 Feb 2015 14:31:08 -0800 (PST)
Raw View
------=_Part_2904_1726805309.1422829868525
Content-Type: multipart/alternative;
boundary="----=_Part_2905_1322822805.1422829868525"
------=_Part_2905_1322822805.1422829868525
Content-Type: text/plain; charset=UTF-8
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
--
---
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2905_1322822805.1422829868525
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">without pretending to having had time to read all the exam=
ples, I have the feeling that this is more or less a direction what I calle=
d in my previous post "generalized templates"<div><br></div><div>mixin memb=
ers {</div><div> void function1();</div><div> int member ;<br><=
/div><div>};<br></div><div><br></div><div>one should just design the correc=
t syntax for this mixins (probably as the body of a template);</div><div><b=
r></div><div>class C {</div><div><br></div><div> pasteMixin<=
;something>;</div><div>};</div><div>//class C will have everything that =
is </div><div><br></div><div>void globalFunction() {</div><div><br></d=
iv><div> trace(pasteMembers<C>);</div><div><br></div><div=
>}</div><div><br></div><div>(please also read my prev. post)</div><div><br>=
</div><div>regards</div><div><br></div><div><br></div><div><br></div><div><=
br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2905_1322822805.1422829868525--
------=_Part_2904_1726805309.1422829868525--
.