Topic: const_up_to_comparator class to provide key


Author: Omer Rosler <omer.rosler@gmail.com>
Date: Tue, 14 Jul 2015 13:23:45 -0700 (PDT)
Raw View
------=_Part_757_728020542.1436905425341
Content-Type: multipart/alternative;
 boundary="----=_Part_758_539008483.1436905425343"

------=_Part_758_539008483.1436905425343
Content-Type: text/plain; charset=UTF-8

This is the first time I share my ideas about C++, so don't be too harsh :)
This post is an attempt to partially solve the problem of key replacement
 in (unordered) associative containers such as
(unordered_)(multi)map, (unordered_)(multi)set* when the object doesn't
move inside the container after replacement and the value *up to the
comparator* is the same.
*The braces () mean optiopnal.
Note that in ordered containers if the value doesn't change (up to the
comparator) so does the position of the object; in unordered this gets
trickier, but we'll get to that later.
My aproach is to create an intermediate class that provides a const-like
access to a object but allows changing it if a comparator yields true (so
the complexity of the assignment operator is the maximum of the complexity
of the object type's assignemnt operator, and the comparator's complexity).
In case of setting a diffrent value this class can either throw some
exception or simply do nothing (up for debate).
By using this class inside the underlying RB tree as the value type
(instead of a simple const type) it will allow iterators to change the
value of the key they hold by calling the wrapper class's assignemnt
iterator.
I haven't decided whether it's smart to make this class public and change
the containers' value type (meaning: big diffrence from older versions for
all 8 containers, although the conversion operator makes old code work all
the same), or simply make it private and convert to container's value type
inside the iterators which will now have setter functions.
The second option has major downsides: The current iterators interface
needs to be changed, instead of holding const key as a public member (like
it does now), it will hold this wrapper class as a private/protected
member, and accessing it must be done using a function call to a getter
that calls a conversion operator (so access is using funtion calls only,
instead of accessing a public member):
template<class Key_type, Compare Comparator = std::equal_to<Key_type> >
struct iterator {
        //other code...
        const Key_type& key() const { //getter
                return m_value; //call conversion operator
        }
        const Key_type& key(const Key_type&x) { //setter
                return m_value = x; //call copy assignment operator of
wrapper class
        }
private:
        const_to_comparison<Key_type, Comparator> m_value
};

(The name 'key' isn't the real function name, for map iterator it will be
'first', and for the set iterator it will be operator* for getter and set
(maybe not a good name in this case) for setter)
It is possible to be made compatible with other versions but will make the
container to hold another public member for the converted type which takes
twice the memory it used to.
So maybe the first option where this wrapper class is public is better (at
least in my opinion).
Maybe there are other places this const-like access can be used.
Well, the wrapper looks basically like this:

namespace std {
template<class _Kty, Compare _Pr = std::equal_to<_Kty> >
class const_to_comparison {
        typedef const_to_comparison<_Kty, _Pr> _Myt;
        typedef _Kty key_type;
        typedef _Pr key_compare;
        static const key_compare comp = _Pr();
public:
        constexpr const_to_comparison() = default;
        constexpr const_to_comparison(const key_type& key) : m_value(key) {}
        constexpr const_to_comparison(const _Myt& other) : m_value(other.key
) {}
        constexpr const_to_comparison(const _Myt&& other) : m_value(other.
key) {}
                _Myt& operator=(const_to_comparison&& other) {
                if (!comp(m_value, other.m_value))
                         std::bad_exception("can't change this value"); //colud
be any other exception or simply do nothing
                m_value = other.m_value; //calling move operator=
        }
        _Myt& operator=(const_to_comparison& other) {
                if (!comp(m_value, other.m_value))
                         std::bad_exception("can't change this value"); //colud
be any other exception or simply do nothing
                m_value = other.m_value; //calling copy operator=
        }
        operator const _Kty&() { //for casting to the container's
value_type inside the iterator
                return m_value;
        }
        ~const_to_comparison() = default;
private:
        key_type m_value;
};
}

For unordered containers this obviously wouldn't work since the hash value
would change every time the key changes and so will the position in the
container, and this whole mechanism will fail.
Therefore the hash value must remain constant after equal key replacement,
so I tried to solve it the simplest way I could think of (I don't really
like this solution so feel free to rip it to shreds):
Save the hash value of the original object in another field and overload
std::hash of this wrapper class to return this field.
Something like this:

namespace std {
template<class _Kty, Compare _Pr = std::equal_to<_Kty>, Hash _Hasher = std::
hash<_Kty> >
class const_to_comparison_and_hash_value : public const_to_comparison < _Kty
, _Pr > {
        typedef const_to_comparison< _Kty, _Pr> _Mybase;
        typedef const_to_comparison_and_hash_value<_Kty, _Pr, _Hasher> _Myt;
        typedef _Kty key_type;
        typedef _Pr key_compare;
        typedef _Hasher key_hash;
        static const key_hash hash = _Hasher();
public:
        constexpr const_to_comparison_and_hash_value() : _Mybase() {}
        constexpr const_to_comparison_and_hash_value(const key_type& other)
: _Mybase(other) {}
        constexpr const_to_comparison_and_hash_value(const _Mybase& other) :
_Mybase(other) {}
        constexpr const_to_comparison_and_hash_value(const _Myt& other) :
_Mybase(other) {}
        constexpr const_to_comparison_and_hash_value(const _Myt&& other) :
_Mybase(other) {}
        _Myt& operator=(const _Myt& other) {
                this->_Mybase::operator=((const _Mybase&)other);
        }
        _Myt& operator=(const _Myt&& other) {
               this->_Mybase::operator=((const _Mybase&&)other);
        }
        ~const_to_comparison_and_hash_value() = default;
        friend struct std::hash<_Myt>;
private:
        const size_t m_hash = hash((const _Kty)this->_Mybase); //initalized
once based on the underlying object
};


template <class _Kty, Compare _Pr = std::equal_to<_Kty>, Hash _Hasher = std
::hash<_Kty> >
struct hash < const_to_comparison_and_hash_value < _Kty, _Pr, _Hasher > > {
        typedef const_to_comparison_and_hash_value<_Kty, _Pr, _Hasher> type;
        size_t oeprator()(const type& x) throw() { //nonthrow since _Hasher
is nonthrow
                return x.m_hash;
        }
};
}

I know this takes more space and this wrapper class should be the same size
of the object type, this is why I don't like it, but I don't see any
diffrent solution in mind (if changing equal keys doesn't move the object I
think the hash value must be saved somehow).
Now all that's left is to add setter functions to the iterators and change
the type being sent to the RB tree to be one of the wrappers.

What do you 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_758_539008483.1436905425343
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>This is the first time I share my ideas about C++, so=
 don&#39;t be too harsh :)<br></div><div>This post is an attempt to partial=
ly solve the problem of key replacement =C2=A0in (unordered) associative co=
ntainers such as</div><div>(unordered_)(multi)map, (unordered_)(multi)set* =
when the object doesn&#39;t move inside the container after replacement and=
 the value <b>up to the comparator</b> is the same.</div><div>*The braces (=
) mean optiopnal.</div><div>Note that in ordered containers if the value do=
esn&#39;t change (up to the comparator) so does the position of the object;=
 in unordered this gets trickier, but we&#39;ll get to that later.</div><di=
v>My aproach is to create an intermediate class that provides a const-like =
access to a object but allows changing it if a comparator yields true (so t=
he complexity of the assignment operator is the maximum of the complexity o=
f the object type&#39;s assignemnt operator, and the comparator&#39;s compl=
exity).</div><div>In case of setting a diffrent value this class can either=
 throw some exception or simply do nothing (up for debate).</div><div>By us=
ing this class inside the underlying RB tree as the value type (instead of =
a simple const type) it will allow iterators to change the value of the key=
 they hold by calling the wrapper class&#39;s assignemnt iterator.</div><di=
v>I haven&#39;t decided whether it&#39;s smart to make this class public an=
d change the containers&#39; value type (meaning: big diffrence from older =
versions for all 8 containers, although the conversion operator makes old c=
ode work all the same), or simply make it private and convert to container&=
#39;s value type inside the iterators which will now have setter functions.=
</div><div>The second option has major downsides: The current iterators int=
erface needs to be changed, instead of holding const key as a public member=
 (like it does now), it will hold this wrapper class as a private/protected=
 member, and accessing it must be done using a function call to a getter th=
at calls a conversion operator (so access is using funtion calls only, inst=
ead of accessing a public member):</div><div><div class=3D"prettyprint" sty=
le=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-word; backgrou=
nd-color: rgb(250, 250, 250);"><code class=3D"prettyprint"><div class=3D"su=
bprettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">tem=
plate</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;<=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">class</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #606;" class=3D"styled-by-prettify">Key_type</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;"=
 class=3D"styled-by-prettify">Compare</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #606;" class=3D"st=
yled-by-prettify">Comparator</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify">equal_to</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><sp=
an style=3D"color: #606;" class=3D"styled-by-prettify">Key_type</span><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">&gt;</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">struct</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> iterator </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:=
 #800;" class=3D"styled-by-prettify">//other code...</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 <=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">const</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #606;" class=3D"styled-by-prettify">Key_type</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">&amp;</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> key</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: #008;" class=3D"=
styled-by-prettify">const</span><font color=3D"#666600"><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;"=
 class=3D"styled-by-prettify">{</span></font><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"s=
tyled-by-prettify">//getter</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">return=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> m_value</=
span><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: #800;" class=3D"styled-by-prettify">//</span><font color=3D"#000=
000"><span style=3D"color: #800;" class=3D"styled-by-prettify">call convers=
ion operator</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br></span></font><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #0=
08;" class=3D"styled-by-prettify">const</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" class=3D"=
styled-by-prettify">Key_type</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">&amp;</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> key</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">(</span><span style=3D"color: #008;" class=3D"styled-by-prettify">co=
nst</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #606;" class=3D"styled-by-prettify">Key_type</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">&amp;</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify">x</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">)</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"> </span><span style=3D"color: #800;" class=3D"styled-by-pre=
ttify">//setter</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><sp=
an style=3D"color: #008;" class=3D"styled-by-prettify">return</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> m_value </span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> x</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"sty=
led-by-prettify">//call copy assignment operator of wrapper class</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">private</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">:</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 const_to_comparison</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">&lt;</span><span style=3D"color: #606;" class=3D"styled=
-by-prettify">Key_type</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: #606;" class=3D"styled-by-prettify">Compar=
ator</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> m_value<br>=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">};</span><=
font color=3D"#666600"></font></div></code></div></div><div><br></div><div>=
(The name &#39;key&#39; isn&#39;t the real function name, for map iterator =
it will be &#39;first&#39;, and for the set iterator it will be operator* f=
or getter and set (maybe not a good name in this case) for setter)</div><di=
v>It is possible to be made compatible with other versions but will make th=
e container to hold another public member for the converted type which take=
s twice the memory it used to.</div><div>So maybe the first option where th=
is wrapper class is public is better (at least in my opinion).</div><div>Ma=
ybe there are other places this const-like access can be used.</div><div>We=
ll, the wrapper looks basically like this:</div><div><br></div><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"prettypri=
nt"><div class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">namespace</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> std </span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">temp=
late</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</=
span><span style=3D"color: #008;" class=3D"styled-by-prettify">class</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> _Kty</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: #=
606;" class=3D"styled-by-prettify">Compare</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> _Pr </span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> std</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">equal_to</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">&lt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">_K=
ty</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">class</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> const_to_comparison </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">typedef</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> const_to_comparis=
on</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify">_Kty</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> _Pr</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">&gt;</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> _Myt</span><span style=3D"color: #660;"=
 class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"=
color: #008;" class=3D"styled-by-prettify">typedef</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> _Kty key_type</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><=
span style=3D"color: #008;" class=3D"styled-by-prettify">typedef</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> _Pr key_compare</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0=
 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">st=
atic</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">const</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> key_compare comp </=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> _Pr</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">();</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color:=
 #008;" class=3D"styled-by-prettify">public</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">:</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">constexpr</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> const_to_comparison</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">()</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">default</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #0=
08;" class=3D"styled-by-prettify">constexpr</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> const_to_comparison</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #0=
08;" class=3D"styled-by-prettify">const</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> key_type</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">&amp;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> key</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">)</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"> m_value<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify">key</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"colo=
r: #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>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">constexpr</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> const_to_comparison</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">const</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> _Myt</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">&amp;</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> other</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 style=3D"color: #000;" class=3D"styled-by-prettify=
"> m_value</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">other</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify">key</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 style=3D"color: #000;" class=3D=
"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"=
color: #008;" class=3D"styled-by-prettify">constexpr</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> const_to_comparison</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"=
color: #008;" class=3D"styled-by-prettify">const</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> _Myt</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">&amp;&amp;</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> other</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 style=3D"color: #000;" class=3D"styled-by-prettify=
"> m_value</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">other</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify">key</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 style=3D"color: #000;" class=3D=
"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 _Myt</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>&amp;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </s=
pan><span style=3D"color: #008;" class=3D"styled-by-prettify">operator</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D(</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">const_to_comparison</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">&amp;&amp;</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> other</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>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">if</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: #000;" class=3D"styled-by-prettify">comp</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify">m_value</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> other</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">.</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">m_value</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">))</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0std</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify">bad_exception</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">(</span><span style=3D"color: #080;" class=3D"styled-by-pret=
tify">&quot;can&#39;t change this value&quot;</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">);</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"st=
yled-by-prettify">//colud be any other exception or simply do nothing</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 m_value </span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color:=
 #000;" class=3D"styled-by-prettify"> other</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">.</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">m_value</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-prettif=
y">//calling move operator=3D</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">&amp;</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D=
"color: #008;" class=3D"styled-by-prettify">operator</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">=3D(</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify">const_to_comparison</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&amp;</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> other</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 style=3D"color: #000;" class=3D"styled-by=
-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">if</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: =
#000;" class=3D"styled-by-prettify">comp</span><span style=3D"color: #660;"=
 class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify">m_value</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> other</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">.</span><span style=3D"color: #000;" class=3D"styled-by-prettify">m_va=
lue</span><span style=3D"color: #660;" class=3D"styled-by-prettify">))</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">:=
:</span><span style=3D"color: #000;" class=3D"styled-by-prettify">bad_excep=
tion</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</spa=
n><span style=3D"color: #080;" class=3D"styled-by-prettify">&quot;can&#39;t=
 change this value&quot;</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #800;" class=3D"styled-by-prettify">//c=
olud be any other exception or simply do nothing</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 m_value </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> other</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy">m_value</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: #800;" class=3D"styled-by-prettify">//calling copy op=
erator=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #0=
08;" class=3D"styled-by-prettify">operator</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">const</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> _Kty</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">&amp;()</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: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #800;" class=3D"styled-by-prettify">//for casting to=
 the container&#39;s value_type inside the iterator</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">return</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> m_value</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </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>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">~</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify">const_to_comparison</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">=3D</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prett=
ify">default</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></s=
pan><span style=3D"color: #008;" class=3D"styled-by-prettify">private</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">:</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 key_type m_value</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">};=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span></div></=
code></div><div class=3D"subprettyprint" style=3D"font-family: monospace; b=
ackground-color: rgb(250, 250, 250);"><br></div><div>For unordered containe=
rs this obviously wouldn&#39;t work since the hash value would change every=
 time the key changes and so will the position in the container, and this w=
hole mechanism will fail.</div><div>Therefore the hash value must remain co=
nstant after equal key replacement, so I tried to solve it the simplest way=
 I could think of (I don&#39;t really like this solution so feel free to ri=
p it to shreds):</div><div>Save the hash value of the original object in an=
other field and overload std::hash of this wrapper class to return this fie=
ld.</div><div>Something like this:</div><div class=3D"prettyprint" style=3D=
"border: 1px solid rgb(187, 187, 187); word-wrap: break-word; background-co=
lor: rgb(250, 250, 250);"><code class=3D"prettyprint"><div class=3D"subpret=
typrint"><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">namespace</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> std </span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">template</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">class</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> _Kty</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-pret=
tify">Compare</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> _Pr </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> std</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">equal_to</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">_Kty</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">&gt;,</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" cl=
ass=3D"styled-by-prettify">Hash</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> _Hasher </span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> std</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">h=
ash</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify">_Kty</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">&gt;</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" =
class=3D"styled-by-prettify">class</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> const_to_comparison_and_hash_value </span><span st=
yle=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: #008=
;" class=3D"styled-by-prettify">public</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> const_to_comparison </span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> _Kty</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> _Pr </span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">&gt;</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0=
 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">typedef</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> const_to_comparison</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">&lt;</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> _Kty</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
_Pr</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> _Mybase</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0=
 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">ty=
pedef</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> cons=
t_to_comparison_and_hash_value</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">&lt;</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify">_Kty</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
_Pr</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> _Hasher</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> _Myt</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">typedef</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> _Kty key_type</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>typedef</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> _=
Pr key_compare</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">typedef</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> _Hasher key_hash</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:=
 #008;" class=3D"styled-by-prettify">static</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">const</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> key_hash hash </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> _Hasher</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">();</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify=
">public</span><span style=3D"color: #660;" class=3D"styled-by-prettify">:<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">constexpr</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> const_to_comparison_and_hash_value</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">()</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">:</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> _Mybase</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">()</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: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">constexpr</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> const_to_comparison_and_hash_value</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">(</span><span style=3D"color: #008;" class=3D"s=
tyled-by-prettify">const</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> key_type</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">&amp;</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> other</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">:</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> _Mybase</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">other</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">{}</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">constexpr</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> const_to_comparison_and_hash_value</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">const</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> _Mybase</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">&amp;</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> other</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"style=
d-by-prettify">:</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> _Mybase</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">other=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">{}</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">constexpr</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> const_to_compa=
rison_and_hash_value</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">(</span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>const</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> _My=
t</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&amp;</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> other</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">:</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> _Mybase</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">other</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{}</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">constexpr</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> const_to_comparison_and_hash_value</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">const</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> _Myt</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">&amp;&amp;</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> other</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: #660;" class=3D"styled-by-prettify">:</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> _Mybase</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify">other</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;" cla=
ss=3D"styled-by-prettify">{}</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">&amp;</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;"=
 class=3D"styled-by-prettify">operator</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">=3D(</span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">const</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> _Myt</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">&amp;</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> other</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>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" =
class=3D"styled-by-prettify">this</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">-&gt;</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">_Mybase</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">::</span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">operator</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">=3D((</span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>const</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> _My=
base</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&amp;)=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify">other</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">);</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">&amp;</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prett=
ify">operator</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">=3D(</span><span style=3D"color: #008;" class=3D"styled-by-prettify">con=
st</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> _Myt</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">&amp;&amp;</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> other</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0</span><span style=3D"color: #008;" class=3D"styled-by-pre=
ttify">this</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>-&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">_Myb=
ase</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">operator</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">=3D((</span><span=
 style=3D"color: #008;" class=3D"styled-by-prettify">const</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> _Mybase</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&amp;&amp;)</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify">other</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">);</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by-prettify">~</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify">const_to_com=
parison_and_hash_value</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">()</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">default</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 <=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">friend</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">struct</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> std</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">hash</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">&lt;</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify">_Myt</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">&gt;;</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">private</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>:</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">const</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> size_t m_hash </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> hash</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">((</span><span style=3D"color: #008;" class=3D"styled-by-prettify">const=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> _Kty</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">this</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">-&gt;</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">_Mybase</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">);</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=
=3D"styled-by-prettify">//initalized once based on the underlying object</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">};</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br><br><br></span><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">template</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">class</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> _Kty</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-pret=
tify">Compare</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> _Pr </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> std</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">equal_to</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">_Kty</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">&gt;,</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" cl=
ass=3D"styled-by-prettify">Hash</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> _Hasher </span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> std</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">h=
ash</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify">_Kty</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">&gt;</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" =
class=3D"styled-by-prettify">struct</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> hash </span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">&lt;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> const_to_comparison_and_hash_value </span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> _Kty</span><span style=3D"color: #660;"=
 class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> _Pr</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> _Hasher </span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </=
span><span style=3D"color: #008;" class=3D"styled-by-prettify">typedef</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> const_to_compa=
rison_and_hash_value</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">&lt;</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy">_Kty</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> _Pr</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> _Hasher</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> type</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 size_t oeprator<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">()(</span><=
span style=3D"color: #008;" class=3D"styled-by-prettify">const</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> type</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&amp;</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> x</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">throw</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">()</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #800;" class=3D"styled-by-prettify">//nonthrow since _Hasher=
 is nonthrow</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">return</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> x</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify">m_hash</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">};</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">}</span></div></code></div><div><br></div><div>I know this takes=
 more space and this wrapper class should be the same size of the object ty=
pe, this is why I don&#39;t like it, but I don&#39;t see any diffrent solut=
ion in mind (if changing equal keys doesn&#39;t move the object I think the=
 hash value must be saved somehow).</div><div>Now all that&#39;s left is to=
 add setter functions to the iterators and change the type being sent to th=
e RB tree to be one of the wrappers.</div><div><br></div><div>What do you t=
hink?</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&quot; 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_758_539008483.1436905425343--
------=_Part_757_728020542.1436905425341--

.


Author: Omer Rosler <omer.rosler@gmail.com>
Date: Tue, 14 Jul 2015 13:37:22 -0700 (PDT)
Raw View
------=_Part_808_592152376.1436906242379
Content-Type: multipart/alternative;
 boundary="----=_Part_809_953061410.1436906242393"

------=_Part_809_953061410.1436906242393
Content-Type: text/plain; charset=UTF-8

Just a note on the last sentance:
If this class is to be publicly viewed than nothing needs to be changed in
the iterator interface, only change the type being sent to the tree.

On Tuesday, July 14, 2015 at 11:23:45 PM UTC+3, Omer Rosler wrote:
>
> This is the first time I share my ideas about C++, so don't be too harsh :)
> This post is an attempt to partially solve the problem of key replacement
>  in (unordered) associative containers such as
> (unordered_)(multi)map, (unordered_)(multi)set* when the object doesn't
> move inside the container after replacement and the value *up to the
> comparator* is the same.
> *The braces () mean optiopnal.
> Note that in ordered containers if the value doesn't change (up to the
> comparator) so does the position of the object; in unordered this gets
> trickier, but we'll get to that later.
> My aproach is to create an intermediate class that provides a const-like
> access to a object but allows changing it if a comparator yields true (so
> the complexity of the assignment operator is the maximum of the complexity
> of the object type's assignemnt operator, and the comparator's complexity).
> In case of setting a diffrent value this class can either throw some
> exception or simply do nothing (up for debate).
> By using this class inside the underlying RB tree as the value type
> (instead of a simple const type) it will allow iterators to change the
> value of the key they hold by calling the wrapper class's assignemnt
> iterator.
> I haven't decided whether it's smart to make this class public and change
> the containers' value type (meaning: big diffrence from older versions for
> all 8 containers, although the conversion operator makes old code work all
> the same), or simply make it private and convert to container's value type
> inside the iterators which will now have setter functions.
> The second option has major downsides: The current iterators interface
> needs to be changed, instead of holding const key as a public member (like
> it does now), it will hold this wrapper class as a private/protected
> member, and accessing it must be done using a function call to a getter
> that calls a conversion operator (so access is using funtion calls only,
> instead of accessing a public member):
> template<class Key_type, Compare Comparator = std::equal_to<Key_type> >
> struct iterator {
>         //other code...
>         const Key_type& key() const { //getter
>                 return m_value; //call conversion operator
>         }
>         const Key_type& key(const Key_type&x) { //setter
>                 return m_value = x; //call copy assignment operator of
> wrapper class
>         }
> private:
>         const_to_comparison<Key_type, Comparator> m_value
> };
>
> (The name 'key' isn't the real function name, for map iterator it will be
> 'first', and for the set iterator it will be operator* for getter and set
> (maybe not a good name in this case) for setter)
> It is possible to be made compatible with other versions but will make the
> container to hold another public member for the converted type which takes
> twice the memory it used to.
> So maybe the first option where this wrapper class is public is better (at
> least in my opinion).
> Maybe there are other places this const-like access can be used.
> Well, the wrapper looks basically like this:
>
> namespace std {
> template<class _Kty, Compare _Pr = std::equal_to<_Kty> >
> class const_to_comparison {
>         typedef const_to_comparison<_Kty, _Pr> _Myt;
>         typedef _Kty key_type;
>         typedef _Pr key_compare;
>         static const key_compare comp = _Pr();
> public:
>         constexpr const_to_comparison() = default;
>         constexpr const_to_comparison(const key_type& key) : m_value(key)
> {}
>         constexpr const_to_comparison(const _Myt& other) : m_value(other.
> key) {}
>         constexpr const_to_comparison(const _Myt&& other) : m_value(other.
> key) {}
>                 _Myt& operator=(const_to_comparison&& other) {
>                 if (!comp(m_value, other.m_value))
>                          std::bad_exception("can't change this value"); //colud
> be any other exception or simply do nothing
>                 m_value = other.m_value; //calling move operator=
>         }
>         _Myt& operator=(const_to_comparison& other) {
>                 if (!comp(m_value, other.m_value))
>                          std::bad_exception("can't change this value"); //colud
> be any other exception or simply do nothing
>                 m_value = other.m_value; //calling copy operator=
>         }
>         operator const _Kty&() { //for casting to the container's
> value_type inside the iterator
>                 return m_value;
>         }
>         ~const_to_comparison() = default;
> private:
>         key_type m_value;
> };
> }
>
> For unordered containers this obviously wouldn't work since the hash value
> would change every time the key changes and so will the position in the
> container, and this whole mechanism will fail.
> Therefore the hash value must remain constant after equal key replacement,
> so I tried to solve it the simplest way I could think of (I don't really
> like this solution so feel free to rip it to shreds):
> Save the hash value of the original object in another field and overload
> std::hash of this wrapper class to return this field.
> Something like this:
>
> namespace std {
> template<class _Kty, Compare _Pr = std::equal_to<_Kty>, Hash _Hasher = std
> ::hash<_Kty> >
> class const_to_comparison_and_hash_value : public const_to_comparison <
> _Kty, _Pr > {
>         typedef const_to_comparison< _Kty, _Pr> _Mybase;
>         typedef const_to_comparison_and_hash_value<_Kty, _Pr, _Hasher>
> _Myt;
>         typedef _Kty key_type;
>         typedef _Pr key_compare;
>         typedef _Hasher key_hash;
>         static const key_hash hash = _Hasher();
> public:
>         constexpr const_to_comparison_and_hash_value() : _Mybase() {}
>         constexpr const_to_comparison_and_hash_value(const key_type& other
> ) : _Mybase(other) {}
>         constexpr const_to_comparison_and_hash_value(const _Mybase& other)
> : _Mybase(other) {}
>         constexpr const_to_comparison_and_hash_value(const _Myt& other) :
> _Mybase(other) {}
>         constexpr const_to_comparison_and_hash_value(const _Myt&& other) :
> _Mybase(other) {}
>         _Myt& operator=(const _Myt& other) {
>                 this->_Mybase::operator=((const _Mybase&)other);
>         }
>         _Myt& operator=(const _Myt&& other) {
>                this->_Mybase::operator=((const _Mybase&&)other);
>         }
>         ~const_to_comparison_and_hash_value() = default;
>         friend struct std::hash<_Myt>;
> private:
>         const size_t m_hash = hash((const _Kty)this->_Mybase); //initalized
> once based on the underlying object
> };
>
>
> template <class _Kty, Compare _Pr = std::equal_to<_Kty>, Hash _Hasher =
> std::hash<_Kty> >
> struct hash < const_to_comparison_and_hash_value < _Kty, _Pr, _Hasher > >
> {
>         typedef const_to_comparison_and_hash_value<_Kty, _Pr, _Hasher>
> type;
>         size_t oeprator()(const type& x) throw() { //nonthrow since
> _Hasher is nonthrow
>                 return x.m_hash;
>         }
> };
> }
>
> I know this takes more space and this wrapper class should be the same
> size of the object type, this is why I don't like it, but I don't see any
> diffrent solution in mind (if changing equal keys doesn't move the object I
> think the hash value must be saved somehow).
> Now all that's left is to add setter functions to the iterators and change
> the type being sent to the RB tree to be one of the wrappers.
>
> What do you 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_809_953061410.1436906242393
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Just a note on the last sentance:<div>If this class is to =
be publicly viewed than nothing needs to be changed in the iterator interfa=
ce, only change the type being sent to the tree.<br><br>On Tuesday, July 14=
, 2015 at 11:23:45 PM UTC+3, Omer Rosler wrote:<blockquote class=3D"gmail_q=
uote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pad=
ding-left: 1ex;"><div dir=3D"ltr"><div>This is the first time I share my id=
eas about C++, so don&#39;t be too harsh :)<br></div><div>This post is an a=
ttempt to partially solve the problem of key replacement =C2=A0in (unordere=
d) associative containers such as</div><div>(unordered_)(multi)map, (unorde=
red_)(multi)set* when the object doesn&#39;t move inside the container afte=
r replacement and the value <b>up to the comparator</b> is the same.</div><=
div>*The braces () mean optiopnal.</div><div>Note that in ordered container=
s if the value doesn&#39;t change (up to the comparator) so does the positi=
on of the object; in unordered this gets trickier, but we&#39;ll get to tha=
t later.</div><div>My aproach is to create an intermediate class that provi=
des a const-like access to a object but allows changing it if a comparator =
yields true (so the complexity of the assignment operator is the maximum of=
 the complexity of the object type&#39;s assignemnt operator, and the compa=
rator&#39;s complexity).</div><div>In case of setting a diffrent value this=
 class can either throw some exception or simply do nothing (up for debate)=
..</div><div>By using this class inside the underlying RB tree as the value =
type (instead of a simple const type) it will allow iterators to change the=
 value of the key they hold by calling the wrapper class&#39;s assignemnt i=
terator.</div><div>I haven&#39;t decided whether it&#39;s smart to make thi=
s class public and change the containers&#39; value type (meaning: big diff=
rence from older versions for all 8 containers, although the conversion ope=
rator makes old code work all the same), or simply make it private and conv=
ert to container&#39;s value type inside the iterators which will now have =
setter functions.</div><div>The second option has major downsides: The curr=
ent iterators interface needs to be changed, instead of holding const key a=
s a public member (like it does now), it will hold this wrapper class as a =
private/protected member, and accessing it must be done using a function ca=
ll to a getter that calls a conversion operator (so access is using funtion=
 calls only, instead of accessing a public member):</div><div><div style=3D=
"border:1px solid rgb(187,187,187);word-wrap:break-word;background-color:rg=
b(250,250,250)"><code><div><span style=3D"color:#008">template</span><span =
style=3D"color:#660">&lt;</span><span style=3D"color:#008">class</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#606">Key_type</span><s=
pan style=3D"color:#660">,</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#606">Compare</span><span style=3D"color:#000"> </span><span =
style=3D"color:#606">Comparator</span><span style=3D"color:#000"> </span><s=
pan style=3D"color:#660">=3D</span><span style=3D"color:#000"> std</span><s=
pan style=3D"color:#660">::</span><span style=3D"color:#000">equal_to</span=
><span style=3D"color:#660">&lt;</span><span style=3D"color:#606">Key_type<=
/span><span style=3D"color:#660">&gt;</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#660">&gt;</span><span style=3D"color:#000"><br></=
span><span style=3D"color:#008">struct</span><span style=3D"color:#000"> it=
erator </span><span style=3D"color:#660">{</span><span style=3D"color:#000"=
><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#800">//other =
code...</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </=
span><span style=3D"color:#008">const</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#606">Key_type</span><span style=3D"color:#660">&a=
mp;</span><span style=3D"color:#000"> key</span><span style=3D"color:#660">=
()</span><span style=3D"color:#000"> </span><span style=3D"color:#008">cons=
t</span><font color=3D"#666600"><span style=3D"color:#000"> </span><span st=
yle=3D"color:#660">{</span></font><span style=3D"color:#000"> </span><span =
style=3D"color:#800">//getter</span><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"colo=
r:#008">return</span><span style=3D"color:#000"> m_value</span><span style=
=3D"color:#660">;</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#800">//</span><font color=3D"#000000"><span style=3D"color:#800">call=
 conversion operator</span><span style=3D"color:#000"><br></span></font><sp=
an style=3D"color:#000">=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"c=
olor:#660">}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 </span><span style=3D"color:#008">const</span><span style=3D"color:#000=
"> </span><span style=3D"color:#606">Key_type</span><span style=3D"color:#6=
60">&amp;</span><span style=3D"color:#000"> key</span><span style=3D"color:=
#660">(</span><span style=3D"color:#008">const</span><span style=3D"color:#=
000"> </span><span style=3D"color:#606">Key_type</span><span style=3D"color=
:#660">&amp;</span><span style=3D"color:#000">x</span><span style=3D"color:=
#660">)</span><span style=3D"color:#000"> </span><span style=3D"color:#660"=
>{</span><span style=3D"color:#000"> </span><span style=3D"color:#800">//se=
tter</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span><sp=
an style=3D"color:#000"> m_value </span><span style=3D"color:#660">=3D</spa=
n><span style=3D"color:#000"> x</span><span style=3D"color:#660">;</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#800">//call copy ass=
ignment operator of wrapper class</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span st=
yle=3D"color:#000"><br></span><span style=3D"color:#008">private</span><spa=
n style=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0=
 =C2=A0 =C2=A0 const_to_comparison</span><span style=3D"color:#660">&lt;</s=
pan><span style=3D"color:#606">Key_type</span><span style=3D"color:#660">,<=
/span><span style=3D"color:#000"> </span><span style=3D"color:#606">Compara=
tor</span><span style=3D"color:#660">&gt;</span><span style=3D"color:#000">=
 m_value<br></span><span style=3D"color:#660">};</span><font color=3D"#6666=
00"></font></div></code></div></div><div><br></div><div>(The name &#39;key&=
#39; isn&#39;t the real function name, for map iterator it will be &#39;fir=
st&#39;, and for the set iterator it will be operator* for getter and set (=
maybe not a good name in this case) for setter)</div><div>It is possible to=
 be made compatible with other versions but will make the container to hold=
 another public member for the converted type which takes twice the memory =
it used to.</div><div>So maybe the first option where this wrapper class is=
 public is better (at least in my opinion).</div><div>Maybe there are other=
 places this const-like access can be used.</div><div>Well, the wrapper loo=
ks basically like this:</div><div><br></div><div style=3D"border:1px solid =
rgb(187,187,187);word-wrap:break-word;background-color:rgb(250,250,250)"><c=
ode><div><span style=3D"color:#008">namespace</span><span style=3D"color:#0=
00"> std </span><span style=3D"color:#660">{</span><span style=3D"color:#00=
0"><br></span><span style=3D"color:#008">template</span><span style=3D"colo=
r:#660">&lt;</span><span style=3D"color:#008">class</span><span style=3D"co=
lor:#000"> _Kty</span><span style=3D"color:#660">,</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#606">Compare</span><span style=3D"co=
lor:#000"> _Pr </span><span style=3D"color:#660">=3D</span><span style=3D"c=
olor:#000"> std</span><span style=3D"color:#660">::</span><span style=3D"co=
lor:#000">equal_to</span><span style=3D"color:#660">&lt;</span><span style=
=3D"color:#000">_Kty</span><span style=3D"color:#660">&gt;</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#660">&gt;</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#008">class</span><span sty=
le=3D"color:#000"> const_to_comparison </span><span style=3D"color:#660">{<=
/span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><sp=
an style=3D"color:#008">typedef</span><span style=3D"color:#000"> const_to_=
comparison</span><span style=3D"color:#660">&lt;</span><span style=3D"color=
:#000">_Kty</span><span style=3D"color:#660">,</span><span style=3D"color:#=
000"> _Pr</span><span style=3D"color:#660">&gt;</span><span style=3D"color:=
#000"> _Myt</span><span style=3D"color:#660">;</span><span style=3D"color:#=
000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">type=
def</span><span style=3D"color:#000"> _Kty key_type</span><span style=3D"co=
lor:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 </span><span style=3D"color:#008">typedef</span><span style=3D"color:#0=
00"> _Pr key_compare</span><span style=3D"color:#660">;</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color=
:#008">static</span><span style=3D"color:#000"> </span><span style=3D"color=
:#008">const</span><span style=3D"color:#000"> key_compare comp </span><spa=
n style=3D"color:#660">=3D</span><span style=3D"color:#000"> _Pr</span><spa=
n style=3D"color:#660">();</span><span style=3D"color:#000"><br></span><spa=
n style=3D"color:#008">public</span><span style=3D"color:#660">:</span><spa=
n style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=
=3D"color:#008">constexpr</span><span style=3D"color:#000"> const_to_compar=
ison</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"> </s=
pan><span style=3D"color:#008">default</span><span style=3D"color:#660">;</=
span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><spa=
n style=3D"color:#008">constexpr</span><span style=3D"color:#000"> const_to=
_comparison</span><span style=3D"color:#660">(</span><span style=3D"color:#=
008">const</span><span style=3D"color:#000"> key_type</span><span style=3D"=
color:#660">&amp;</span><span style=3D"color:#000"> key</span><span style=
=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#660">:</span><span style=3D"color:#000"> m_value</span><span style=3D=
"color:#660">(</span><span style=3D"color:#000">key</span><span style=3D"co=
lor:#660">)</span><span style=3D"color:#000"> </span><span style=3D"color:#=
660">{}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </=
span><span style=3D"color:#008">constexpr</span><span style=3D"color:#000">=
 const_to_comparison</span><span style=3D"color:#660">(</span><span style=
=3D"color:#008">const</span><span style=3D"color:#000"> _Myt</span><span st=
yle=3D"color:#660">&amp;</span><span style=3D"color:#000"> other</span><spa=
n style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#660">:</span><span style=3D"color:#000"> m_value</span><span s=
tyle=3D"color:#660">(</span><span style=3D"color:#000">other</span><span st=
yle=3D"color:#660">.</span><span style=3D"color:#000">key</span><span style=
=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#660">{}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 </span><span style=3D"color:#008">constexpr</span><span style=3D"color:=
#000"> const_to_comparison</span><span style=3D"color:#660">(</span><span s=
tyle=3D"color:#008">const</span><span style=3D"color:#000"> _Myt</span><spa=
n style=3D"color:#660">&amp;&amp;</span><span style=3D"color:#000"> other</=
span><span style=3D"color:#660">)</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#660">:</span><span style=3D"color:#000"> m_value</spa=
n><span style=3D"color:#660">(</span><span style=3D"color:#000">other</span=
><span style=3D"color:#660">.</span><span style=3D"color:#000">key</span><s=
pan style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#660">{}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</span><span style=3D"color:#=
660">&amp;</span><span style=3D"color:#000"> </span><span style=3D"color:#0=
08">operator</span><span style=3D"color:#660">=3D(</span><span style=3D"col=
or:#000">const_to_comparison</span><span style=3D"color:#660">&amp;&amp;</s=
pan><span style=3D"color:#000"> other</span><span style=3D"color:#660">)</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#660">{</span><=
span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 </span><span style=3D"color:#008">if</span><span style=3D"color:=
#000"> </span><span style=3D"color:#660">(!</span><span style=3D"color:#000=
">comp</span><span style=3D"color:#660">(</span><span style=3D"color:#000">=
m_value</span><span style=3D"color:#660">,</span><span style=3D"color:#000"=
> other</span><span style=3D"color:#660">.</span><span style=3D"color:#000"=
>m_value</span><span style=3D"color:#660">))</span><span style=3D"color:#00=
0"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0std</span><span style=3D"color:#660">::</span><span=
 style=3D"color:#000">bad_exception</span><span style=3D"color:#660">(</spa=
n><span style=3D"color:#080">&quot;can&#39;t change this value&quot;</span>=
<span style=3D"color:#660">);</span><span style=3D"color:#000"> </span><spa=
n style=3D"color:#800">//colud be any other exception or simply do nothing<=
/span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 m_value </span><span style=3D"color:#660">=3D</span><span=
 style=3D"color:#000"> other</span><span style=3D"color:#660">.</span><span=
 style=3D"color:#000">m_value</span><span style=3D"color:#660">;</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#800">//calling move op=
erator=3D</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
</span><span style=3D"color:#660">}</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</span><span style=3D"color:#660">&amp;</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#008">operator</=
span><span style=3D"color:#660">=3D(</span><span style=3D"color:#000">const=
_to_comparison</span><span style=3D"color:#660">&amp;</span><span style=3D"=
color:#000"> other</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>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><=
span style=3D"color:#008">if</span><span style=3D"color:#000"> </span><span=
 style=3D"color:#660">(!</span><span style=3D"color:#000">comp</span><span =
style=3D"color:#660">(</span><span style=3D"color:#000">m_value</span><span=
 style=3D"color:#660">,</span><span style=3D"color:#000"> other</span><span=
 style=3D"color:#660">.</span><span style=3D"color:#000">m_value</span><spa=
n style=3D"color:#660">))</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0std</span><span style=3D"color:#660">::</span><span style=3D"color:#0=
00">bad_exception</span><span style=3D"color:#660">(</span><span style=3D"c=
olor:#080">&quot;can&#39;t change this value&quot;</span><span style=3D"col=
or:#660">);</span><span style=3D"color:#000"> </span><span style=3D"color:#=
800">//colud be any other exception or simply do nothing</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
 m_value </span><span style=3D"color:#660">=3D</span><span style=3D"color:#=
000"> other</span><span style=3D"color:#660">.</span><span style=3D"color:#=
000">m_value</span><span style=3D"color:#660">;</span><span style=3D"color:=
#000"> </span><span style=3D"color:#800">//calling copy operator=3D</span><=
span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span styl=
e=3D"color:#660">}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 </span><span style=3D"color:#008">operator</span><span style=3D"=
color:#000"> </span><span style=3D"color:#008">const</span><span style=3D"c=
olor:#000"> _Kty</span><span style=3D"color:#660">&amp;()</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#800">//for casting to the containe=
r&#39;s value_type inside the iterator</span><span style=3D"color:#000"><br=
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=
=3D"color:#008">return</span><span style=3D"color:#000"> m_value</span><spa=
n style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0=
 =C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span style=3D"col=
or:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660">=
~</span><span style=3D"color:#000">const_to_comparison</span><span style=3D=
"color:#660">()</span><span style=3D"color:#000"> </span><span style=3D"col=
or:#660">=3D</span><span style=3D"color:#000"> </span><span style=3D"color:=
#008">default</span><span style=3D"color:#660">;</span><span style=3D"color=
:#000"><br></span><span style=3D"color:#008">private</span><span style=3D"c=
olor:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 key_type m_value</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></span><span style=3D"color:#660">}</span></div></code>=
</div><div style=3D"font-family:monospace;background-color:rgb(250,250,250)=
"><br></div><div>For unordered containers this obviously wouldn&#39;t work =
since the hash value would change every time the key changes and so will th=
e position in the container, and this whole mechanism will fail.</div><div>=
Therefore the hash value must remain constant after equal key replacement, =
so I tried to solve it the simplest way I could think of (I don&#39;t reall=
y like this solution so feel free to rip it to shreds):</div><div>Save the =
hash value of the original object in another field and overload std::hash o=
f this wrapper class to return this field.</div><div>Something like this:</=
div><div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;ba=
ckground-color:rgb(250,250,250)"><code><div><span style=3D"color:#000"><br>=
</span><span style=3D"color:#008">namespace</span><span style=3D"color:#000=
"> std </span><span style=3D"color:#660">{</span><span style=3D"color:#000"=
><br></span><span style=3D"color:#008">template</span><span style=3D"color:=
#660">&lt;</span><span style=3D"color:#008">class</span><span style=3D"colo=
r:#000"> _Kty</span><span style=3D"color:#660">,</span><span style=3D"color=
:#000"> </span><span style=3D"color:#606">Compare</span><span style=3D"colo=
r:#000"> _Pr </span><span style=3D"color:#660">=3D</span><span style=3D"col=
or:#000"> std</span><span style=3D"color:#660">::</span><span style=3D"colo=
r:#000">equal_to</span><span style=3D"color:#660">&lt;</span><span style=3D=
"color:#000">_Kty</span><span style=3D"color:#660">&gt;,</span><span style=
=3D"color:#000"> </span><span style=3D"color:#606">Hash</span><span style=
=3D"color:#000"> _Hasher </span><span style=3D"color:#660">=3D</span><span =
style=3D"color:#000"> std</span><span style=3D"color:#660">::</span><span s=
tyle=3D"color:#000">hash</span><span style=3D"color:#660">&lt;</span><span =
style=3D"color:#000">_Kty</span><span style=3D"color:#660">&gt;</span><span=
 style=3D"color:#000"> </span><span style=3D"color:#660">&gt;</span><span s=
tyle=3D"color:#000"><br></span><span style=3D"color:#008">class</span><span=
 style=3D"color:#000"> const_to_comparison_and_hash_value </span><span styl=
e=3D"color:#660">:</span><span style=3D"color:#000"> </span><span style=3D"=
color:#008">public</span><span style=3D"color:#000"> const_to_comparison </=
span><span style=3D"color:#660">&lt;</span><span style=3D"color:#000"> _Kty=
</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> _Pr <=
/span><span style=3D"color:#660">&gt;</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typedef</span><s=
pan style=3D"color:#000"> const_to_comparison</span><span style=3D"color:#6=
60">&lt;</span><span style=3D"color:#000"> _Kty</span><span style=3D"color:=
#660">,</span><span style=3D"color:#000"> _Pr</span><span style=3D"color:#6=
60">&gt;</span><span style=3D"color:#000"> _Mybase</span><span style=3D"col=
or:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0=
 </span><span style=3D"color:#008">typedef</span><span style=3D"color:#000"=
> const_to_comparison_and_hash_value</span><span style=3D"color:#660">&lt;<=
/span><span style=3D"color:#000">_Kty</span><span style=3D"color:#660">,</s=
pan><span style=3D"color:#000"> _Pr</span><span style=3D"color:#660">,</spa=
n><span style=3D"color:#000"> _Hasher</span><span style=3D"color:#660">&gt;=
</span><span style=3D"color:#000"> _Myt</span><span style=3D"color:#660">;<=
/span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><sp=
an style=3D"color:#008">typedef</span><span style=3D"color:#000"> _Kty key_=
type</span><span style=3D"color:#660">;</span><span style=3D"color:#000"><b=
r>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typedef</sp=
an><span style=3D"color:#000"> _Pr key_compare</span><span style=3D"color:#=
660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </s=
pan><span style=3D"color:#008">typedef</span><span style=3D"color:#000"> _H=
asher key_hash</span><span style=3D"color:#660">;</span><span style=3D"colo=
r:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">s=
tatic</span><span style=3D"color:#000"> </span><span style=3D"color:#008">c=
onst</span><span style=3D"color:#000"> key_hash hash </span><span style=3D"=
color:#660">=3D</span><span style=3D"color:#000"> _Hasher</span><span style=
=3D"color:#660">();</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#008">public</span><span style=3D"color:#660">:</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color=
:#008">constexpr</span><span style=3D"color:#000"> const_to_comparison_and_=
hash_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">=
 _Mybase</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"><=
br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr<=
/span><span style=3D"color:#000"> const_to_comparison_and_hash_value</span>=
<span style=3D"color:#660">(</span><span style=3D"color:#008">const</span><=
span style=3D"color:#000"> key_type</span><span style=3D"color:#660">&amp;<=
/span><span style=3D"color:#000"> other</span><span style=3D"color:#660">)<=
/span><span style=3D"color:#000"> </span><span style=3D"color:#660">:</span=
><span style=3D"color:#000"> _Mybase</span><span style=3D"color:#660">(</sp=
an><span style=3D"color:#000">other</span><span style=3D"color:#660">)</spa=
n><span style=3D"color:#000"> </span><span style=3D"color:#660">{}</span><s=
pan style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=
=3D"color:#008">constexpr</span><span style=3D"color:#000"> const_to_compar=
ison_and_hash_value</span><span style=3D"color:#660">(</span><span style=3D=
"color:#008">const</span><span style=3D"color:#000"> _Mybase</span><span st=
yle=3D"color:#660">&amp;</span><span style=3D"color:#000"> other</span><spa=
n style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#660">:</span><span style=3D"color:#000"> _Mybase</span><span s=
tyle=3D"color:#660">(</span><span style=3D"color:#000">other</span><span st=
yle=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">{}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</span><span style=3D=
"color:#000"> const_to_comparison_and_hash_value</span><span style=3D"color=
:#660">(</span><span style=3D"color:#008">const</span><span style=3D"color:=
#000"> _Myt</span><span style=3D"color:#660">&amp;</span><span style=3D"col=
or:#000"> other</span><span style=3D"color:#660">)</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#660">:</span><span style=3D"color:#0=
00"> _Mybase</span><span style=3D"color:#660">(</span><span style=3D"color:=
#000">other</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>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexp=
r</span><span style=3D"color:#000"> const_to_comparison_and_hash_value</spa=
n><span style=3D"color:#660">(</span><span style=3D"color:#008">const</span=
><span style=3D"color:#000"> _Myt</span><span style=3D"color:#660">&amp;&am=
p;</span><span style=3D"color:#000"> other</span><span style=3D"color:#660"=
>)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">:</s=
pan><span style=3D"color:#000"> _Mybase</span><span style=3D"color:#660">(<=
/span><span style=3D"color:#000">other</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>=C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</span><spa=
n style=3D"color:#660">&amp;</span><span style=3D"color:#000"> </span><span=
 style=3D"color:#008">operator</span><span style=3D"color:#660">=3D(</span>=
<span style=3D"color:#008">const</span><span style=3D"color:#000"> _Myt</sp=
an><span style=3D"color:#660">&amp;</span><span style=3D"color:#000"> other=
</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"colo=
r:#008">this</span><span style=3D"color:#660">-&gt;</span><span style=3D"co=
lor:#000">_Mybase</span><span style=3D"color:#660">::</span><span style=3D"=
color:#008">operator</span><span style=3D"color:#660">=3D((</span><span sty=
le=3D"color:#008">const</span><span style=3D"color:#000"> _Mybase</span><sp=
an style=3D"color:#660">&amp;)</span><span style=3D"color:#000">other</span=
><span style=3D"color:#660">);</span><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</span><span style=3D"c=
olor:#660">&amp;</span><span style=3D"color:#000"> </span><span style=3D"co=
lor:#008">operator</span><span style=3D"color:#660">=3D(</span><span style=
=3D"color:#008">const</span><span style=3D"color:#000"> _Myt</span><span st=
yle=3D"color:#660">&amp;&amp;</span><span style=3D"color:#000"> other</span=
><span style=3D"color:#660">)</span><span style=3D"color:#000"> </span><spa=
n style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0=
 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#008"=
>this</span><span style=3D"color:#660">-&gt;</span><span style=3D"color:#00=
0">_Mybase</span><span style=3D"color:#660">::</span><span style=3D"color:#=
008">operator</span><span style=3D"color:#660">=3D((</span><span style=3D"c=
olor:#008">const</span><span style=3D"color:#000"> _Mybase</span><span styl=
e=3D"color:#660">&amp;&amp;)</span><span style=3D"color:#000">other</span><=
span style=3D"color:#660">);</span><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color=
:#660">~</span><span style=3D"color:#000">const_to_comparison_and_hash_valu=
e</span><span style=3D"color:#660">()</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> </span=
><span style=3D"color:#008">default</span><span style=3D"color:#660">;</spa=
n><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span s=
tyle=3D"color:#008">friend</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#008">struct</span><span style=3D"color:#000"> std</span><spa=
n style=3D"color:#660">::</span><span style=3D"color:#000">hash</span><span=
 style=3D"color:#660">&lt;</span><span style=3D"color:#000">_Myt</span><spa=
n style=3D"color:#660">&gt;;</span><span style=3D"color:#000"><br></span><s=
pan style=3D"color:#008">private</span><span style=3D"color:#660">:</span><=
span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span styl=
e=3D"color:#008">const</span><span style=3D"color:#000"> size_t m_hash </sp=
an><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> hash</s=
pan><span style=3D"color:#660">((</span><span style=3D"color:#008">const</s=
pan><span style=3D"color:#000"> _Kty</span><span style=3D"color:#660">)</sp=
an><span style=3D"color:#008">this</span><span style=3D"color:#660">-&gt;</=
span><span style=3D"color:#000">_Mybase</span><span style=3D"color:#660">);=
</span><span style=3D"color:#000"> </span><span style=3D"color:#800">//init=
alized once based on the underlying object</span><span style=3D"color:#000"=
><br></span><span style=3D"color:#660">};</span><span style=3D"color:#000">=
<br><br><br></span><span style=3D"color:#008">template</span><span style=3D=
"color:#000"> </span><span style=3D"color:#660">&lt;</span><span style=3D"c=
olor:#008">class</span><span style=3D"color:#000"> _Kty</span><span style=
=3D"color:#660">,</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#606">Compare</span><span style=3D"color:#000"> _Pr </span><span style=
=3D"color:#660">=3D</span><span style=3D"color:#000"> std</span><span style=
=3D"color:#660">::</span><span style=3D"color:#000">equal_to</span><span st=
yle=3D"color:#660">&lt;</span><span style=3D"color:#000">_Kty</span><span s=
tyle=3D"color:#660">&gt;,</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#606">Hash</span><span style=3D"color:#000"> _Hasher </span><s=
pan style=3D"color:#660">=3D</span><span style=3D"color:#000"> std</span><s=
pan style=3D"color:#660">::</span><span style=3D"color:#000">hash</span><sp=
an style=3D"color:#660">&lt;</span><span style=3D"color:#000">_Kty</span><s=
pan style=3D"color:#660">&gt;</span><span style=3D"color:#000"> </span><spa=
n style=3D"color:#660">&gt;</span><span style=3D"color:#000"><br></span><sp=
an style=3D"color:#008">struct</span><span style=3D"color:#000"> hash </spa=
n><span style=3D"color:#660">&lt;</span><span style=3D"color:#000"> const_t=
o_comparison_and_hash_value </span><span style=3D"color:#660">&lt;</span><s=
pan style=3D"color:#000"> _Kty</span><span style=3D"color:#660">,</span><sp=
an style=3D"color:#000"> _Pr</span><span style=3D"color:#660">,</span><span=
 style=3D"color:#000"> _Hasher </span><span style=3D"color:#660">&gt;</span=
><span style=3D"color:#000"> </span><span style=3D"color:#660">&gt;</span><=
span style=3D"color:#000"> </span><span style=3D"color:#660">{</span><span =
style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"=
color:#008">typedef</span><span style=3D"color:#000"> const_to_comparison_a=
nd_hash_value</span><span style=3D"color:#660">&lt;</span><span style=3D"co=
lor:#000">_Kty</span><span style=3D"color:#660">,</span><span style=3D"colo=
r:#000"> _Pr</span><span style=3D"color:#660">,</span><span style=3D"color:=
#000"> _Hasher</span><span style=3D"color:#660">&gt;</span><span style=3D"c=
olor:#000"> type</span><span style=3D"color:#660">;</span><span style=3D"co=
lor:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 size_t oeprator</span><span style=
=3D"color:#660">()(</span><span style=3D"color:#008">const</span><span styl=
e=3D"color:#000"> type</span><span style=3D"color:#660">&amp;</span><span s=
tyle=3D"color:#000"> x</span><span style=3D"color:#660">)</span><span style=
=3D"color:#000"> </span><span style=3D"color:#008">throw</span><span style=
=3D"color:#660">()</span><span style=3D"color:#000"> </span><span style=3D"=
color:#660">{</span><span style=3D"color:#000"> </span><span style=3D"color=
:#800">//nonthrow since _Hasher is nonthrow</span><span style=3D"color:#000=
"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span =
style=3D"color:#008">return</span><span style=3D"color:#000"> x</span><span=
 style=3D"color:#660">.</span><span style=3D"color:#000">m_hash</span><span=
 style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span style=3D"colo=
r:#000"><br></span><span style=3D"color:#660">};</span><span style=3D"color=
:#000"><br></span><span style=3D"color:#660">}</span></div></code></div><di=
v><br></div><div>I know this takes more space and this wrapper class should=
 be the same size of the object type, this is why I don&#39;t like it, but =
I don&#39;t see any diffrent solution in mind (if changing equal keys doesn=
&#39;t move the object I think the hash value must be saved somehow).</div>=
<div>Now all that&#39;s left is to add setter functions to the iterators an=
d change the type being sent to the RB tree to be one of the wrappers.</div=
><div><br></div><div>What do you think?</div></div></blockquote></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&quot; 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_809_953061410.1436906242393--
------=_Part_808_592152376.1436906242379--

.


Author: edward.catmur@mavensecurities.com
Date: Wed, 15 Jul 2015 04:49:26 -0700 (PDT)
Raw View
------=_Part_6151_641019297.1436960966169
Content-Type: text/plain; charset=UTF-8

First, an important point: the ordered containers don't care about
equality; the test for equivalence under the comparator is that of
incomparability. So you should use std::less in place of std::equal_to, and !comp(lhs,
rhs) && !comp(rhs, lhs) in place of comp(lhs, rhs).

Second, although I recognise that key modification is an occasional
requirement, I don't think it's worth or necessary altering the containers.
It's sufficient to use as key type a wrapper class with a mutable field,
possibly protecting access to that field by checking key equivalence.

For example:

template<class Key>
class mutable_key
{
public:
    mutable_key(Key const& value) : value{value} {}
    operator Key const& () const { return value; }
    template<class Container>
    void mutate(Container const& container, Key const& new_value) const {
        auto&& comp = container.key_comp();
        assert(!comp(value, new_value) && !comp(new_value, value));
        value = new_value;
    }
private:
    Key mutable value;
};

Note that key_comp works with both set and map.

And for unordered containers:

template<class Key>
class mutable_unordered_key
{
public:
    mutable_unordered_key(Key const& value) : value{value} {}
    operator Key const& () const { return value; }
    template<class Container>
    void mutate(Container const& container, Key const& new_value) const {
        auto&& hash = container.hash_function();
        auto&& eq = container.key_eq();
        assert(hash(new_value) == hash(value));
        assert(eq(new_value, value));
        value = new_value;
    }
private:
    Key mutable value;
};

Example of usage:

    auto comp = [](int lhs, int rhs) { return (lhs % 10) < (rhs % 10); };
    std::map<mutable_key<int>, int, decltype(comp)> m{{{1, 1}, {2, 2}}, comp
};
    m.find(1)->first.mutate(m, 11);
    assert(m.begin()->first == 11);

    auto hash = [](int value) { return std::hash<int>()(value % 10); };
    auto eq = [](int lhs, int rhs) { return (lhs % 10) == (rhs % 10); };
    std::unordered_map<mutable_unordered_key<int>, int, decltype(hash),
decltype(eq)> um{{{1, 1}, {2, 2}}, 0, hash, eq};
    um.find(1)->first.mutate(um, 11);
    assert(um.find(1)->first == 11);

Full example: http://coliru.stacked-crooked.com/a/14c679ab93edf32f

On Tuesday, 14 July 2015 21:37:22 UTC+1, Omer Rosler wrote:
>
> Just a note on the last sentance:
> If this class is to be publicly viewed than nothing needs to be changed in
> the iterator interface, only change the type being sent to the tree.
>
> On Tuesday, July 14, 2015 at 11:23:45 PM UTC+3, Omer Rosler wrote:
>>
>> This is the first time I share my ideas about C++, so don't be too harsh
>> :)
>> This post is an attempt to partially solve the problem of key replacement
>>  in (unordered) associative containers such as
>> (unordered_)(multi)map, (unordered_)(multi)set* when the object doesn't
>> move inside the container after replacement and the value *up to the
>> comparator* is the same.
>> *The braces () mean optiopnal.
>> Note that in ordered containers if the value doesn't change (up to the
>> comparator) so does the position of the object; in unordered this gets
>> trickier, but we'll get to that later.
>> My aproach is to create an intermediate class that provides a const-like
>> access to a object but allows changing it if a comparator yields true (so
>> the complexity of the assignment operator is the maximum of the complexity
>> of the object type's assignemnt operator, and the comparator's complexity).
>> In case of setting a diffrent value this class can either throw some
>> exception or simply do nothing (up for debate).
>> By using this class inside the underlying RB tree as the value type
>> (instead of a simple const type) it will allow iterators to change the
>> value of the key they hold by calling the wrapper class's assignemnt
>> iterator.
>> I haven't decided whether it's smart to make this class public and change
>> the containers' value type (meaning: big diffrence from older versions for
>> all 8 containers, although the conversion operator makes old code work all
>> the same), or simply make it private and convert to container's value type
>> inside the iterators which will now have setter functions.
>> The second option has major downsides: The current iterators interface
>> needs to be changed, instead of holding const key as a public member (like
>> it does now), it will hold this wrapper class as a private/protected
>> member, and accessing it must be done using a function call to a getter
>> that calls a conversion operator (so access is using funtion calls only,
>> instead of accessing a public member):
>> template<class Key_type, Compare Comparator = std::equal_to<Key_type> >
>> struct iterator {
>>         //other code...
>>         const Key_type& key() const { //getter
>>                 return m_value; //call conversion operator
>>         }
>>         const Key_type& key(const Key_type&x) { //setter
>>                 return m_value = x; //call copy assignment operator of
>> wrapper class
>>         }
>> private:
>>         const_to_comparison<Key_type, Comparator> m_value
>> };
>>
>> (The name 'key' isn't the real function name, for map iterator it will be
>> 'first', and for the set iterator it will be operator* for getter and set
>> (maybe not a good name in this case) for setter)
>> It is possible to be made compatible with other versions but will make
>> the container to hold another public member for the converted type which
>> takes twice the memory it used to.
>> So maybe the first option where this wrapper class is public is better
>> (at least in my opinion).
>> Maybe there are other places this const-like access can be used.
>> Well, the wrapper looks basically like this:
>>
>> namespace std {
>> template<class _Kty, Compare _Pr = std::equal_to<_Kty> >
>> class const_to_comparison {
>>         typedef const_to_comparison<_Kty, _Pr> _Myt;
>>         typedef _Kty key_type;
>>         typedef _Pr key_compare;
>>         static const key_compare comp = _Pr();
>> public:
>>         constexpr const_to_comparison() = default;
>>         constexpr const_to_comparison(const key_type& key) : m_value(key)
>> {}
>>         constexpr const_to_comparison(const _Myt& other) : m_value(other.
>> key) {}
>>         constexpr const_to_comparison(const _Myt&& other) : m_value(other
>> .key) {}
>>                 _Myt& operator=(const_to_comparison&& other) {
>>                 if (!comp(m_value, other.m_value))
>>                          std::bad_exception("can't change this value"); //colud
>> be any other exception or simply do nothing
>>                 m_value = other.m_value; //calling move operator=
>>         }
>>         _Myt& operator=(const_to_comparison& other) {
>>                 if (!comp(m_value, other.m_value))
>>                          std::bad_exception("can't change this value"); //colud
>> be any other exception or simply do nothing
>>                 m_value = other.m_value; //calling copy operator=
>>         }
>>         operator const _Kty&() { //for casting to the container's
>> value_type inside the iterator
>>                 return m_value;
>>         }
>>         ~const_to_comparison() = default;
>> private:
>>         key_type m_value;
>> };
>> }
>>
>> For unordered containers this obviously wouldn't work since the hash
>> value would change every time the key changes and so will the position in
>> the container, and this whole mechanism will fail.
>> Therefore the hash value must remain constant after equal key
>> replacement, so I tried to solve it the simplest way I could think of (I
>> don't really like this solution so feel free to rip it to shreds):
>> Save the hash value of the original object in another field and overload
>> std::hash of this wrapper class to return this field.
>> Something like this:
>>
>> namespace std {
>> template<class _Kty, Compare _Pr = std::equal_to<_Kty>, Hash _Hasher =
>> std::hash<_Kty> >
>> class const_to_comparison_and_hash_value : public const_to_comparison <
>> _Kty, _Pr > {
>>         typedef const_to_comparison< _Kty, _Pr> _Mybase;
>>         typedef const_to_comparison_and_hash_value<_Kty, _Pr, _Hasher>
>> _Myt;
>>         typedef _Kty key_type;
>>         typedef _Pr key_compare;
>>         typedef _Hasher key_hash;
>>         static const key_hash hash = _Hasher();
>> public:
>>         constexpr const_to_comparison_and_hash_value() : _Mybase() {}
>>         constexpr const_to_comparison_and_hash_value(const key_type&
>> other) : _Mybase(other) {}
>>         constexpr const_to_comparison_and_hash_value(const _Mybase& other
>> ) : _Mybase(other) {}
>>         constexpr const_to_comparison_and_hash_value(const _Myt& other) :
>> _Mybase(other) {}
>>         constexpr const_to_comparison_and_hash_value(const _Myt&& other)
>> : _Mybase(other) {}
>>         _Myt& operator=(const _Myt& other) {
>>                 this->_Mybase::operator=((const _Mybase&)other);
>>         }
>>         _Myt& operator=(const _Myt&& other) {
>>                this->_Mybase::operator=((const _Mybase&&)other);
>>         }
>>         ~const_to_comparison_and_hash_value() = default;
>>         friend struct std::hash<_Myt>;
>> private:
>>         const size_t m_hash = hash((const _Kty)this->_Mybase); //initalized
>> once based on the underlying object
>> };
>>
>>
>> template <class _Kty, Compare _Pr = std::equal_to<_Kty>, Hash _Hasher =
>> std::hash<_Kty> >
>> struct hash < const_to_comparison_and_hash_value < _Kty, _Pr, _Hasher > >
>> {
>>         typedef const_to_comparison_and_hash_value<_Kty, _Pr, _Hasher>
>> type;
>>         size_t oeprator()(const type& x) throw() { //nonthrow since
>> _Hasher is nonthrow
>>                 return x.m_hash;
>>         }
>> };
>> }
>>
>> I know this takes more space and this wrapper class should be the same
>> size of the object type, this is why I don't like it, but I don't see any
>> diffrent solution in mind (if changing equal keys doesn't move the object I
>> think the hash value must be saved somehow).
>> Now all that's left is to add setter functions to the iterators and
>> change the type being sent to the RB tree to be one of the wrappers.
>>
>> What do you think?
>>
>
--


This e-mail together with any attachments (the "Message") is confidential
and may contain privileged information. If you are not the intended
recipient or if you have received this e-mail in error, please notify the
sender immediately and permanently delete this Message from your system.
Do not copy, disclose or distribute the information contained in this
Message.



Maven Securities Holding Ltd (No. 07505438), Maven Trading Ltd (No.
07511928), Maven Derivatives Ltd (No. 07511840) & Maven Europe Ltd (No.
08966593) are registered as companies in England and their registered
office address is Camomile Court, 23 Camomile St London EC3A 7LL, United
Kingdom and their VAT No. is 135539016. Maven Derivatives Ltd only is
authorised and regulated by the Financial Conduct Authority (FRN 607267).

--

---
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_6151_641019297.1436960966169
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>First, an important point: the ordered containers don=
&#39;t care about equality; the test for equivalence under the comparator i=
s that of incomparability. So you should use std::less in place of std::equ=
al_to, and <font face=3D"courier new, monospace">!comp(lhs, rhs) &amp;&amp;=
 !comp(rhs, lhs)</font> in place of <font face=3D"courier new, monospace">c=
omp(lhs, rhs)</font>.</div><div><br></div>Second, although I recognise that=
 key modification is an occasional requirement, I don&#39;t think it&#39;s =
worth or necessary altering the containers. It&#39;s sufficient to use as k=
ey type a wrapper class with a mutable field, possibly protecting access to=
 that field by checking key equivalence.<div><br></div><div>For example:</d=
iv><div><br></div><div><div class=3D"prettyprint" style=3D"border: 1px soli=
d rgb(187, 187, 187); word-wrap: break-word; background-color: rgb(250, 250=
, 250);"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">template</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"c=
olor: #008;" class=3D"styled-by-prettify">class</span><span style=3D"color:=
 #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" c=
lass=3D"styled-by-prettify">Key</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">&gt;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">class</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> mutable_key<br></span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">publi=
c</span><span style=3D"color: #660;" class=3D"styled-by-prettify">:</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =
mutable_key</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>(</span><span style=3D"color: #606;" class=3D"styled-by-prettify">Key</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">const</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&amp;</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> value</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 style=3D"color: #000;" class=3D"styled-by=
-prettify"> value</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify">va=
lue</span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">{}</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">operator</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #606;" class=3D"styled-by-prettify">Key</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">const</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">&amp;</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">()</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><span style=3D"color: #008;" class=3D"styled-by-prettify">const</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;=
" class=3D"styled-by-prettify">return</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> value</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prett=
ify">template</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">&lt;</span><span style=3D"color: #008;" class=3D"styled-by-prettify">cla=
ss</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #606;" class=3D"styled-by-prettify">Container</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">void</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"> mutate</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"co=
lor: #606;" class=3D"styled-by-prettify">Container</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;=
" class=3D"styled-by-prettify">const</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">&amp;</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> container</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettif=
y">Key</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </s=
pan><span style=3D"color: #008;" class=3D"styled-by-prettify">const</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">&amp;</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> new_value</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: #0=
08;" class=3D"styled-by-prettify">const</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: #000;" class=3D"styled-by=
-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">auto</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">&amp;&amp;</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> comp </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> container</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify">key_comp</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">();</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D=
"styled-by-prettify">assert</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">(!</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify">comp</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">value<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> new_value</span><sp=
an 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">&amp;&amp;</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: #000;" class=3D"=
styled-by-prettify">comp</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify">new_value</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> valu=
e</span><span style=3D"color: #660;" class=3D"styled-by-prettify">));</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 value </span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> new_value</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r>=C2=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
></span><span style=3D"color: #008;" class=3D"styled-by-prettify">private</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">:</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </s=
pan><span style=3D"color: #606;" class=3D"styled-by-prettify">Key</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">mutable</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> value</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">};</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br></span></div></code></div><div><br></div><div>Note tha=
t key_comp works with both set and map.</div><div><br></div><div>And for un=
ordered containers:</div><div><br></div><div><div class=3D"prettyprint" sty=
le=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-word; backgrou=
nd-color: rgb(250, 250, 250);"><code class=3D"prettyprint"><div class=3D"su=
bprettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">tem=
plate</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;<=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">class</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #606;" class=3D"styled-by-prettify">Key</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">&gt;</span><span style=3D"color:=
 #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #008;=
" class=3D"styled-by-prettify">class</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> mutable_unordered_key<br></span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">public</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">:</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>=C2=A0 =C2=A0 mutable_unordered_key</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #=
606;" class=3D"styled-by-prettify">Key</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"s=
tyled-by-prettify">const</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">&amp;</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> value</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"> value</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify">value</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">{}</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">operator</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-pret=
tify">Key</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">const</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">&amp;</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">()</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;"=
 class=3D"styled-by-prettify">const</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">re=
turn</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> value=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><s=
pan 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=
: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">template</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">class</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" cl=
ass=3D"styled-by-prettify">Container</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">&gt;</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" c=
lass=3D"styled-by-prettify">void</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> mutate</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">(</span><span style=3D"color: #606;" class=3D"styled-b=
y-prettify">Container</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify=
">const</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&am=
p;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> contain=
er</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #606;" class=3D"styled-by-prettify">Key</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">const</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">&amp;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> new_value</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">const</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: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0=
 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prett=
ify">auto</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&=
amp;&amp;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
hash </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> container</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">hash_function</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">();</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">aut=
o</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&amp;&amp=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> eq </spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"> container</span><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify">key_eq</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">();</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><sp=
an style=3D"color: #008;" class=3D"styled-by-prettify">assert</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">hash</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify">new_value</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">=3D=3D</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> hash</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify">value</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">));</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>assert</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify">eq</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">new_value</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> value</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">));</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 value </span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> new_value</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">private</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">:</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #606;" c=
lass=3D"styled-by-prettify">Key</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">mutable</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> value</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">;</span><span style=3D"color: #000;" class=3D"styled-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></span></div><=
/code></div><div><br>Example of usage:</div></div><div><br></div><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"prettypri=
nt"><div class=3D"subprettyprint"><span style=3D"color: #000;" class=3D"sty=
led-by-prettify">=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D=
"styled-by-prettify">auto</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> comp </span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">[](</=
span><span style=3D"color: #008;" class=3D"styled-by-prettify">int</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> lhs</span><span st=
yle=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: #008=
;" class=3D"styled-by-prettify">int</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> rhs</span><span style=3D"color: #660;" class=3D"s=
tyled-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 style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #008;" class=3D"styled-by-prettify">return</span><spa=
n 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=
: #000;" class=3D"styled-by-prettify">lhs </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: #066;" class=3D"style=
d-by-prettify">10</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify">rhs </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">%</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=3D"styl=
ed-by-prettify">10</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">);</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: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0=
 std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify">map</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify">mutable_key</span><span sty=
le=3D"color: #080;" class=3D"styled-by-prettify">&lt;int&gt;</span><span st=
yle=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: #008=
;" class=3D"styled-by-prettify">int</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pre=
ttify">decltype</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">comp=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)&gt;</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> m</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">{{{</span><span style=
=3D"color: #066;" class=3D"styled-by-prettify">1</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: #066;" class=3D"=
styled-by-prettify">1</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">},</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</spa=
n><span style=3D"color: #066;" class=3D"styled-by-prettify">2</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #06=
6;" class=3D"styled-by-prettify">2</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">}},</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> comp</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">};</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><br>=C2=A0 =C2=A0 m</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy">find</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(<=
/span><span style=3D"color: #066;" class=3D"styled-by-prettify">1</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">)-&gt;</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">first</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">mutate</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify">m</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #066;" class=3D"styled-by-prettify">11=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">);</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">assert</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify">m</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color: #0=
08;" class=3D"styled-by-prettify">begin</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">()-&gt;</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify">first </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">=3D=3D</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #066;" class=3D"styled-by=
-prettify">11</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">);</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><=
br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-pre=
ttify">auto</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> hash </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">[](</span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">int</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> value</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 style=3D"color: #000;" class=3D"styled-by=
-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify=
">return</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> s=
td</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify">hash</span><span=
 style=3D"color: #080;" class=3D"styled-by-prettify">&lt;int&gt;</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">()(</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 style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #066;" clas=
s=3D"styled-by-prettify">10</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">);</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"><br>=C2=
=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>auto</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> eq <=
/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 styl=
e=3D"color: #660;" class=3D"styled-by-prettify">[](</span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">int</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> lhs</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">int</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> rhs</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n 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=
: #008;" class=3D"styled-by-prettify">return</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">lhs </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: #066;" class=3D"styled-by-prettify">10</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">=3D=3D</span><span style=3D"color:=
 #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">rhs </span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">%</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #066;" class=3D"styled-by-prettify">10</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">};</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 std</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">unordered_map</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">mutable_unordered_key</span><span =
style=3D"color: #080;" class=3D"styled-by-prettify">&lt;int&gt;</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: #=
008;" class=3D"styled-by-prettify">int</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">decltype</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">h=
ash</span><span style=3D"color: #660;" class=3D"styled-by-prettify">),</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">decltype</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify">eq</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">)&gt;</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> um</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">{{{</span><span style=3D"color: #066;" class=3D"styled-=
by-prettify">1</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #066;" class=3D"styled-by-prettify">1</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 style=3D"color: #066;" cla=
ss=3D"styled-by-prettify">2</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #066;" class=3D"styled-by-prettify">2=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">}},</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #066;" class=3D"styled-by-prettify">0</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> hash</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> eq</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">};</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br>=C2=A0 =C2=A0 um</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">find</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</=
span><span style=3D"color: #066;" class=3D"styled-by-prettify">1</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">)-&gt;</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify">first</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">mutate</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify">um</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #066;" class=3D"styled-by-prettify">1=
1</span><span style=3D"color: #660;" class=3D"styled-by-prettify">);</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0=
 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">assert</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify">um</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">find</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">(</span><span style=3D"color: #066;" class=
=3D"styled-by-prettify">1</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">)-&gt;</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify">first </span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">=3D=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: #066;" class=3D"styled-by-prettify">11</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">);</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></div></cod=
e></div><div><br>Full example:=C2=A0http://coliru.stacked-crooked.com/a/14c=
679ab93edf32f</div><br>On Tuesday, 14 July 2015 21:37:22 UTC+1, Omer Rosler=
  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">Just =
a note on the last sentance:<div>If this class is to be publicly viewed tha=
n nothing needs to be changed in the iterator interface, only change the ty=
pe being sent to the tree.<br><br>On Tuesday, July 14, 2015 at 11:23:45 PM =
UTC+3, Omer Rosler 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>This is the first time I share my ideas about C++, so don&#39=
;t be too harsh :)<br></div><div>This post is an attempt to partially solve=
 the problem of key replacement =C2=A0in (unordered) associative containers=
 such as</div><div>(unordered_)(multi)map, (unordered_)(multi)set* when the=
 object doesn&#39;t move inside the container after replacement and the val=
ue <b>up to the comparator</b> is the same.</div><div>*The braces () mean o=
ptiopnal.</div><div>Note that in ordered containers if the value doesn&#39;=
t change (up to the comparator) so does the position of the object; in unor=
dered this gets trickier, but we&#39;ll get to that later.</div><div>My apr=
oach is to create an intermediate class that provides a const-like access t=
o a object but allows changing it if a comparator yields true (so the compl=
exity of the assignment operator is the maximum of the complexity of the ob=
ject type&#39;s assignemnt operator, and the comparator&#39;s complexity).<=
/div><div>In case of setting a diffrent value this class can either throw s=
ome exception or simply do nothing (up for debate).</div><div>By using this=
 class inside the underlying RB tree as the value type (instead of a simple=
 const type) it will allow iterators to change the value of the key they ho=
ld by calling the wrapper class&#39;s assignemnt iterator.</div><div>I have=
n&#39;t decided whether it&#39;s smart to make this class public and change=
 the containers&#39; value type (meaning: big diffrence from older versions=
 for all 8 containers, although the conversion operator makes old code work=
 all the same), or simply make it private and convert to container&#39;s va=
lue type inside the iterators which will now have setter functions.</div><d=
iv>The second option has major downsides: The current iterators interface n=
eeds to be changed, instead of holding const key as a public member (like i=
t does now), it will hold this wrapper class as a private/protected member,=
 and accessing it must be done using a function call to a getter that calls=
 a conversion operator (so access is using funtion calls only, instead of a=
ccessing a public member):</div><div><div style=3D"border:1px solid rgb(187=
,187,187);word-wrap:break-word;background-color:rgb(250,250,250)"><code><di=
v><span style=3D"color:#008">template</span><span style=3D"color:#660">&lt;=
</span><span style=3D"color:#008">class</span><span style=3D"color:#000"> <=
/span><span style=3D"color:#606">Key_type</span><span style=3D"color:#660">=
,</span><span style=3D"color:#000"> </span><span style=3D"color:#606">Compa=
re</span><span style=3D"color:#000"> </span><span style=3D"color:#606">Comp=
arator</span><span style=3D"color:#000"> </span><span style=3D"color:#660">=
=3D</span><span style=3D"color:#000"> std</span><span style=3D"color:#660">=
::</span><span style=3D"color:#000">equal_to</span><span style=3D"color:#66=
0">&lt;</span><span style=3D"color:#606">Key_type</span><span style=3D"colo=
r:#660">&gt;</span><span style=3D"color:#000"> </span><span style=3D"color:=
#660">&gt;</span><span style=3D"color:#000"><br></span><span style=3D"color=
:#008">struct</span><span style=3D"color:#000"> iterator </span><span style=
=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0=
 =C2=A0 </span><span style=3D"color:#800">//other code...</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color=
:#008">const</span><span style=3D"color:#000"> </span><span style=3D"color:=
#606">Key_type</span><span style=3D"color:#660">&amp;</span><span style=3D"=
color:#000"> key</span><span style=3D"color:#660">()</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#008">const</span><font color=3D"#6=
66600"><span style=3D"color:#000"> </span><span style=3D"color:#660">{</spa=
n></font><span style=3D"color:#000"> </span><span style=3D"color:#800">//ge=
tter</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span><sp=
an style=3D"color:#000"> m_value</span><span style=3D"color:#660">;</span><=
span style=3D"color:#000"> </span><span style=3D"color:#800">//</span><font=
 color=3D"#000000"><span style=3D"color:#800">call conversion operator</spa=
n><span style=3D"color:#000"><br></span></font><span style=3D"color:#000">=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span=
 style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D=
"color:#008">const</span><span style=3D"color:#000"> </span><span style=3D"=
color:#606">Key_type</span><span style=3D"color:#660">&amp;</span><span sty=
le=3D"color:#000"> key</span><span style=3D"color:#660">(</span><span style=
=3D"color:#008">const</span><span style=3D"color:#000"> </span><span style=
=3D"color:#606">Key_type</span><span style=3D"color:#660">&amp;</span><span=
 style=3D"color:#000">x</span><span style=3D"color:#660">)</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"=
color:#000"> </span><span style=3D"color:#800">//setter</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
 </span><span style=3D"color:#008">return</span><span style=3D"color:#000">=
 m_value </span><span style=3D"color:#660">=3D</span><span style=3D"color:#=
000"> x</span><span style=3D"color:#660">;</span><span style=3D"color:#000"=
> </span><span style=3D"color:#800">//call copy assignment operator of wrap=
per class</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
</span><span style=3D"color:#660">}</span><span style=3D"color:#000"><br></=
span><span style=3D"color:#008">private</span><span style=3D"color:#660">:<=
/span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 const_to_c=
omparison</span><span style=3D"color:#660">&lt;</span><span style=3D"color:=
#606">Key_type</span><span style=3D"color:#660">,</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#606">Comparator</span><span style=3D"=
color:#660">&gt;</span><span style=3D"color:#000"> m_value<br></span><span =
style=3D"color:#660">};</span><font color=3D"#666600"></font></div></code><=
/div></div><div><br></div><div>(The name &#39;key&#39; isn&#39;t the real f=
unction name, for map iterator it will be &#39;first&#39;, and for the set =
iterator it will be operator* for getter and set (maybe not a good name in =
this case) for setter)</div><div>It is possible to be made compatible with =
other versions but will make the container to hold another public member fo=
r the converted type which takes twice the memory it used to.</div><div>So =
maybe the first option where this wrapper class is public is better (at lea=
st in my opinion).</div><div>Maybe there are other places this const-like a=
ccess can be used.</div><div>Well, the wrapper looks basically like this:</=
div><div><br></div><div style=3D"border:1px solid rgb(187,187,187);word-wra=
p:break-word;background-color:rgb(250,250,250)"><code><div><span style=3D"c=
olor:#008">namespace</span><span style=3D"color:#000"> std </span><span sty=
le=3D"color:#660">{</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#008">template</span><span style=3D"color:#660">&lt;</span><span =
style=3D"color:#008">class</span><span style=3D"color:#000"> _Kty</span><sp=
an style=3D"color:#660">,</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#606">Compare</span><span style=3D"color:#000"> _Pr </span><sp=
an style=3D"color:#660">=3D</span><span style=3D"color:#000"> std</span><sp=
an style=3D"color:#660">::</span><span style=3D"color:#000">equal_to</span>=
<span style=3D"color:#660">&lt;</span><span style=3D"color:#000">_Kty</span=
><span style=3D"color:#660">&gt;</span><span style=3D"color:#000"> </span><=
span style=3D"color:#660">&gt;</span><span style=3D"color:#000"><br></span>=
<span style=3D"color:#008">class</span><span style=3D"color:#000"> const_to=
_comparison </span><span style=3D"color:#660">{</span><span style=3D"color:=
#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typ=
edef</span><span style=3D"color:#000"> const_to_comparison</span><span styl=
e=3D"color:#660">&lt;</span><span style=3D"color:#000">_Kty</span><span sty=
le=3D"color:#660">,</span><span style=3D"color:#000"> _Pr</span><span style=
=3D"color:#660">&gt;</span><span style=3D"color:#000"> _Myt</span><span sty=
le=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 </span><span style=3D"color:#008">typedef</span><span style=3D"c=
olor:#000"> _Kty key_type</span><span style=3D"color:#660">;</span><span st=
yle=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"co=
lor:#008">typedef</span><span style=3D"color:#000"> _Pr key_compare</span><=
span style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">static</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#008">const</span><span style=
=3D"color:#000"> key_compare comp </span><span style=3D"color:#660">=3D</sp=
an><span style=3D"color:#000"> _Pr</span><span style=3D"color:#660">();</sp=
an><span style=3D"color:#000"><br></span><span style=3D"color:#008">public<=
/span><span style=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</span>=
<span style=3D"color:#000"> const_to_comparison</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:#008">d=
efault</span><span style=3D"color:#660">;</span><span style=3D"color:#000">=
<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr=
</span><span style=3D"color:#000"> const_to_comparison</span><span style=3D=
"color:#660">(</span><span style=3D"color:#008">const</span><span style=3D"=
color:#000"> key_type</span><span style=3D"color:#660">&amp;</span><span st=
yle=3D"color:#000"> key</span><span style=3D"color:#660">)</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#660">:</span><span style=3D"=
color:#000"> m_value</span><span style=3D"color:#660">(</span><span style=
=3D"color:#000">key</span><span style=3D"color:#660">)</span><span style=3D=
"color:#000"> </span><span style=3D"color:#660">{}</span><span style=3D"col=
or:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">=
constexpr</span><span style=3D"color:#000"> const_to_comparison</span><span=
 style=3D"color:#660">(</span><span style=3D"color:#008">const</span><span =
style=3D"color:#000"> _Myt</span><span style=3D"color:#660">&amp;</span><sp=
an style=3D"color:#000"> other</span><span style=3D"color:#660">)</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#660">:</span><span st=
yle=3D"color:#000"> m_value</span><span style=3D"color:#660">(</span><span =
style=3D"color:#000">other</span><span style=3D"color:#660">.</span><span s=
tyle=3D"color:#000">key</span><span style=3D"color:#660">)</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#660">{}</span><span style=3D=
"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#0=
08">constexpr</span><span style=3D"color:#000"> const_to_comparison</span><=
span style=3D"color:#660">(</span><span style=3D"color:#008">const</span><s=
pan style=3D"color:#000"> _Myt</span><span style=3D"color:#660">&amp;&amp;<=
/span><span style=3D"color:#000"> other</span><span style=3D"color:#660">)<=
/span><span style=3D"color:#000"> </span><span style=3D"color:#660">:</span=
><span style=3D"color:#000"> m_value</span><span style=3D"color:#660">(</sp=
an><span style=3D"color:#000">other</span><span style=3D"color:#660">.</spa=
n><span style=3D"color:#000">key</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>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 _Myt</span><span style=3D"color:#660">&amp;</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#008">operator</span><span style=3D"c=
olor:#660">=3D(</span><span style=3D"color:#000">const_to_comparison</span>=
<span style=3D"color:#660">&amp;&amp;</span><span style=3D"color:#000"> oth=
er</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"=
color:#008">if</span><span style=3D"color:#000"> </span><span style=3D"colo=
r:#660">(!</span><span style=3D"color:#000">comp</span><span style=3D"color=
:#660">(</span><span style=3D"color:#000">m_value</span><span style=3D"colo=
r:#660">,</span><span style=3D"color:#000"> other</span><span style=3D"colo=
r:#660">.</span><span style=3D"color:#000">m_value</span><span style=3D"col=
or:#660">))</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0std</span=
><span style=3D"color:#660">::</span><span style=3D"color:#000">bad_excepti=
on</span><span style=3D"color:#660">(</span><span style=3D"color:#080">&quo=
t;can&#39;t change this value&quot;</span><span style=3D"color:#660">);</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#800">//colud be=
 any other exception or simply do nothing</span><span style=3D"color:#000">=
<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 m_value </span>=
<span style=3D"color:#660">=3D</span><span style=3D"color:#000"> other</spa=
n><span style=3D"color:#660">.</span><span style=3D"color:#000">m_value</sp=
an><span style=3D"color:#660">;</span><span style=3D"color:#000"> </span><s=
pan style=3D"color:#800">//calling move operator=3D</span><span style=3D"co=
lor:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660"=
>}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</s=
pan><span style=3D"color:#660">&amp;</span><span style=3D"color:#000"> </sp=
an><span style=3D"color:#008">operator</span><span style=3D"color:#660">=3D=
(</span><span style=3D"color:#000">const_to_comparison</span><span style=3D=
"color:#660">&amp;</span><span style=3D"color:#000"> other</span><span styl=
e=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"=
color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">if</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#660">(!</span><spa=
n style=3D"color:#000">comp</span><span style=3D"color:#660">(</span><span =
style=3D"color:#000">m_value</span><span style=3D"color:#660">,</span><span=
 style=3D"color:#000"> other</span><span style=3D"color:#660">.</span><span=
 style=3D"color:#000">m_value</span><span style=3D"color:#660">))</span><sp=
an style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0std</span><span style=3D"color=
:#660">::</span><span style=3D"color:#000">bad_exception</span><span style=
=3D"color:#660">(</span><span style=3D"color:#080">&quot;can&#39;t change t=
his value&quot;</span><span style=3D"color:#660">);</span><span style=3D"co=
lor:#000"> </span><span style=3D"color:#800">//colud be any other exception=
 or simply do nothing</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 m_value </span><span style=3D"col=
or:#660">=3D</span><span style=3D"color:#000"> other</span><span style=3D"c=
olor:#660">.</span><span style=3D"color:#000">m_value</span><span style=3D"=
color:#660">;</span><span style=3D"color:#000"> </span><span style=3D"color=
:#800">//calling copy operator=3D</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span st=
yle=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"co=
lor:#008">operator</span><span style=3D"color:#000"> </span><span style=3D"=
color:#008">const</span><span style=3D"color:#000"> _Kty</span><span style=
=3D"color:#660">&amp;()</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#660">{</span><span style=3D"color:#000"> </span><span style=3D"=
color:#800">//for casting to the container&#39;s value_type inside the iter=
ator</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span><sp=
an style=3D"color:#000"> m_value</span><span style=3D"color:#660">;</span><=
span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span styl=
e=3D"color:#660">}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 </span><span style=3D"color:#660">~</span><span style=3D"color:#=
000">const_to_comparison</span><span style=3D"color:#660">()</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#660">=3D</span><span style=
=3D"color:#000"> </span><span style=3D"color:#008">default</span><span styl=
e=3D"color:#660">;</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#008">private</span><span style=3D"color:#660">:</span><span styl=
e=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 key_type m_value</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></span><span =
style=3D"color:#660">}</span></div></code></div><div style=3D"font-family:m=
onospace;background-color:rgb(250,250,250)"><br></div><div>For unordered co=
ntainers this obviously wouldn&#39;t work since the hash value would change=
 every time the key changes and so will the position in the container, and =
this whole mechanism will fail.</div><div>Therefore the hash value must rem=
ain constant after equal key replacement, so I tried to solve it the simple=
st way I could think of (I don&#39;t really like this solution so feel free=
 to rip it to shreds):</div><div>Save the hash value of the original object=
 in another field and overload std::hash of this wrapper class to return th=
is field.</div><div>Something like this:</div><div style=3D"border:1px soli=
d rgb(187,187,187);word-wrap:break-word;background-color:rgb(250,250,250)">=
<code><div><span style=3D"color:#000"><br></span><span style=3D"color:#008"=
>namespace</span><span style=3D"color:#000"> std </span><span style=3D"colo=
r:#660">{</span><span style=3D"color:#000"><br></span><span style=3D"color:=
#008">template</span><span style=3D"color:#660">&lt;</span><span style=3D"c=
olor:#008">class</span><span style=3D"color:#000"> _Kty</span><span style=
=3D"color:#660">,</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#606">Compare</span><span style=3D"color:#000"> _Pr </span><span style=
=3D"color:#660">=3D</span><span style=3D"color:#000"> std</span><span style=
=3D"color:#660">::</span><span style=3D"color:#000">equal_to</span><span st=
yle=3D"color:#660">&lt;</span><span style=3D"color:#000">_Kty</span><span s=
tyle=3D"color:#660">&gt;,</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#606">Hash</span><span style=3D"color:#000"> _Hasher </span><s=
pan style=3D"color:#660">=3D</span><span style=3D"color:#000"> std</span><s=
pan style=3D"color:#660">::</span><span style=3D"color:#000">hash</span><sp=
an style=3D"color:#660">&lt;</span><span style=3D"color:#000">_Kty</span><s=
pan style=3D"color:#660">&gt;</span><span style=3D"color:#000"> </span><spa=
n style=3D"color:#660">&gt;</span><span style=3D"color:#000"><br></span><sp=
an style=3D"color:#008">class</span><span style=3D"color:#000"> const_to_co=
mparison_and_hash_value </span><span style=3D"color:#660">:</span><span sty=
le=3D"color:#000"> </span><span style=3D"color:#008">public</span><span sty=
le=3D"color:#000"> const_to_comparison </span><span style=3D"color:#660">&l=
t;</span><span style=3D"color:#000"> _Kty</span><span style=3D"color:#660">=
,</span><span style=3D"color:#000"> _Pr </span><span style=3D"color:#660">&=
gt;</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{</=
span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><spa=
n style=3D"color:#008">typedef</span><span style=3D"color:#000"> const_to_c=
omparison</span><span style=3D"color:#660">&lt;</span><span style=3D"color:=
#000"> _Kty</span><span style=3D"color:#660">,</span><span style=3D"color:#=
000"> _Pr</span><span style=3D"color:#660">&gt;</span><span style=3D"color:=
#000"> _Mybase</span><span style=3D"color:#660">;</span><span style=3D"colo=
r:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">t=
ypedef</span><span style=3D"color:#000"> const_to_comparison_and_hash_value=
</span><span style=3D"color:#660">&lt;</span><span style=3D"color:#000">_Kt=
y</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> _Pr<=
/span><span style=3D"color:#660">,</span><span style=3D"color:#000"> _Hashe=
r</span><span style=3D"color:#660">&gt;</span><span style=3D"color:#000"> _=
Myt</span><span style=3D"color:#660">;</span><span style=3D"color:#000"><br=
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typedef</spa=
n><span style=3D"color:#000"> _Kty key_type</span><span style=3D"color:#660=
">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span=
><span style=3D"color:#008">typedef</span><span style=3D"color:#000"> _Pr k=
ey_compare</span><span style=3D"color:#660">;</span><span style=3D"color:#0=
00"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typed=
ef</span><span style=3D"color:#000"> _Hasher key_hash</span><span style=3D"=
color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 </span><span style=3D"color:#008">static</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#008">const</span><span style=3D"color:#000=
"> key_hash hash </span><span style=3D"color:#660">=3D</span><span style=3D=
"color:#000"> _Hasher</span><span style=3D"color:#660">();</span><span styl=
e=3D"color:#000"><br></span><span style=3D"color:#008">public</span><span s=
tyle=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</span><span style=
=3D"color:#000"> const_to_comparison_and_hash_value</span><span style=3D"co=
lor:#660">()</span><span style=3D"color:#000"> </span><span style=3D"color:=
#660">:</span><span style=3D"color:#000"> _Mybase</span><span style=3D"colo=
r:#660">()</span><span style=3D"color:#000"> </span><span style=3D"color:#6=
60">{}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </s=
pan><span style=3D"color:#008">constexpr</span><span style=3D"color:#000"> =
const_to_comparison_and_hash_value</span><span style=3D"color:#660">(</span=
><span style=3D"color:#008">const</span><span style=3D"color:#000"> key_typ=
e</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#000"> =
other</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> =
</span><span style=3D"color:#660">:</span><span style=3D"color:#000"> _Myba=
se</span><span style=3D"color:#660">(</span><span style=3D"color:#000">othe=
r</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> </sp=
an><span style=3D"color:#660">{}</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</span>=
<span style=3D"color:#000"> const_to_comparison_and_hash_value</span><span =
style=3D"color:#660">(</span><span style=3D"color:#008">const</span><span s=
tyle=3D"color:#000"> _Mybase</span><span style=3D"color:#660">&amp;</span><=
span style=3D"color:#000"> other</span><span style=3D"color:#660">)</span><=
span style=3D"color:#000"> </span><span style=3D"color:#660">:</span><span =
style=3D"color:#000"> _Mybase</span><span style=3D"color:#660">(</span><spa=
n style=3D"color:#000">other</span><span style=3D"color:#660">)</span><span=
 style=3D"color:#000"> </span><span style=3D"color:#660">{}</span><span sty=
le=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"col=
or:#008">constexpr</span><span style=3D"color:#000"> const_to_comparison_an=
d_hash_value</span><span style=3D"color:#660">(</span><span style=3D"color:=
#008">const</span><span style=3D"color:#000"> _Myt</span><span style=3D"col=
or:#660">&amp;</span><span style=3D"color:#000"> other</span><span style=3D=
"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"colo=
r:#660">:</span><span style=3D"color:#000"> _Mybase</span><span style=3D"co=
lor:#660">(</span><span style=3D"color:#000">other</span><span style=3D"col=
or:#660">)</span><span style=3D"color:#000"> </span><span style=3D"color:#6=
60">{}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </s=
pan><span style=3D"color:#008">constexpr</span><span style=3D"color:#000"> =
const_to_comparison_and_hash_value</span><span style=3D"color:#660">(</span=
><span style=3D"color:#008">const</span><span style=3D"color:#000"> _Myt</s=
pan><span style=3D"color:#660">&amp;&amp;</span><span style=3D"color:#000">=
 other</span><span style=3D"color:#660">)</span><span style=3D"color:#000">=
 </span><span style=3D"color:#660">:</span><span style=3D"color:#000"> _Myb=
ase</span><span style=3D"color:#660">(</span><span style=3D"color:#000">oth=
er</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#660">{}</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</span><span style=3D"color:#660">&amp;</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#008">operator</spa=
n><span style=3D"color:#660">=3D(</span><span style=3D"color:#008">const</s=
pan><span style=3D"color:#000"> _Myt</span><span style=3D"color:#660">&amp;=
</span><span style=3D"color:#000"> other</span><span style=3D"color:#660">)=
</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{</spa=
n><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 </span><span style=3D"color:#008">this</span><span style=3D"c=
olor:#660">-&gt;</span><span style=3D"color:#000">_Mybase</span><span style=
=3D"color:#660">::</span><span style=3D"color:#008">operator</span><span st=
yle=3D"color:#660">=3D((</span><span style=3D"color:#008">const</span><span=
 style=3D"color:#000"> _Mybase</span><span style=3D"color:#660">&amp;)</spa=
n><span style=3D"color:#000">other</span><span style=3D"color:#660">);</spa=
n><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span s=
tyle=3D"color:#660">}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 _Myt</span><span style=3D"color:#660">&amp;</span><span style=
=3D"color:#000"> </span><span style=3D"color:#008">operator</span><span sty=
le=3D"color:#660">=3D(</span><span style=3D"color:#008">const</span><span s=
tyle=3D"color:#000"> _Myt</span><span style=3D"color:#660">&amp;&amp;</span=
><span style=3D"color:#000"> other</span><span style=3D"color:#660">)</span=
><span style=3D"color:#000"> </span><span style=3D"color:#660">{</span><spa=
n style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
 =C2=A0</span><span style=3D"color:#008">this</span><span style=3D"color:#6=
60">-&gt;</span><span style=3D"color:#000">_Mybase</span><span style=3D"col=
or:#660">::</span><span style=3D"color:#008">operator</span><span style=3D"=
color:#660">=3D((</span><span style=3D"color:#008">const</span><span style=
=3D"color:#000"> _Mybase</span><span style=3D"color:#660">&amp;&amp;)</span=
><span style=3D"color:#000">other</span><span style=3D"color:#660">);</span=
><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span st=
yle=3D"color:#660">}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 </span><span style=3D"color:#660">~</span><span style=3D"color:#=
000">const_to_comparison_and_hash_value</span><span style=3D"color:#660">()=
</span><span style=3D"color:#000"> </span><span style=3D"color:#660">=3D</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#008">default</=
span><span style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">friend</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#008">struct</span><sp=
an style=3D"color:#000"> std</span><span style=3D"color:#660">::</span><spa=
n style=3D"color:#000">hash</span><span style=3D"color:#660">&lt;</span><sp=
an style=3D"color:#000">_Myt</span><span style=3D"color:#660">&gt;;</span><=
span style=3D"color:#000"><br></span><span style=3D"color:#008">private</sp=
an><span style=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=A0=
 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">const</span><span s=
tyle=3D"color:#000"> size_t m_hash </span><span style=3D"color:#660">=3D</s=
pan><span style=3D"color:#000"> hash</span><span style=3D"color:#660">((</s=
pan><span style=3D"color:#008">const</span><span style=3D"color:#000"> _Kty=
</span><span style=3D"color:#660">)</span><span style=3D"color:#008">this</=
span><span style=3D"color:#660">-&gt;</span><span style=3D"color:#000">_Myb=
ase</span><span style=3D"color:#660">);</span><span style=3D"color:#000"> <=
/span><span style=3D"color:#800">//initalized once based on the underlying =
object</span><span style=3D"color:#000"><br></span><span style=3D"color:#66=
0">};</span><span style=3D"color:#000"><br><br><br></span><span style=3D"co=
lor:#008">template</span><span style=3D"color:#000"> </span><span style=3D"=
color:#660">&lt;</span><span style=3D"color:#008">class</span><span style=
=3D"color:#000"> _Kty</span><span style=3D"color:#660">,</span><span style=
=3D"color:#000"> </span><span style=3D"color:#606">Compare</span><span styl=
e=3D"color:#000"> _Pr </span><span style=3D"color:#660">=3D</span><span sty=
le=3D"color:#000"> std</span><span style=3D"color:#660">::</span><span styl=
e=3D"color:#000">equal_to</span><span style=3D"color:#660">&lt;</span><span=
 style=3D"color:#000">_Kty</span><span style=3D"color:#660">&gt;,</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#606">Hash</span><span=
 style=3D"color:#000"> _Hasher </span><span style=3D"color:#660">=3D</span>=
<span style=3D"color:#000"> std</span><span style=3D"color:#660">::</span><=
span style=3D"color:#000">hash</span><span style=3D"color:#660">&lt;</span>=
<span style=3D"color:#000">_Kty</span><span style=3D"color:#660">&gt;</span=
><span style=3D"color:#000"> </span><span style=3D"color:#660">&gt;</span><=
span style=3D"color:#000"><br></span><span style=3D"color:#008">struct</spa=
n><span style=3D"color:#000"> hash </span><span style=3D"color:#660">&lt;</=
span><span style=3D"color:#000"> const_to_comparison_and_hash_value </span>=
<span style=3D"color:#660">&lt;</span><span style=3D"color:#000"> _Kty</spa=
n><span style=3D"color:#660">,</span><span style=3D"color:#000"> _Pr</span>=
<span style=3D"color:#660">,</span><span style=3D"color:#000"> _Hasher </sp=
an><span style=3D"color:#660">&gt;</span><span style=3D"color:#000"> </span=
><span style=3D"color:#660">&gt;</span><span style=3D"color:#000"> </span><=
span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typedef</span><span sty=
le=3D"color:#000"> const_to_comparison_and_hash_value</span><span style=3D"=
color:#660">&lt;</span><span style=3D"color:#000">_Kty</span><span style=3D=
"color:#660">,</span><span style=3D"color:#000"> _Pr</span><span style=3D"c=
olor:#660">,</span><span style=3D"color:#000"> _Hasher</span><span style=3D=
"color:#660">&gt;</span><span style=3D"color:#000"> type</span><span style=
=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0=
 =C2=A0 size_t oeprator</span><span style=3D"color:#660">()(</span><span st=
yle=3D"color:#008">const</span><span style=3D"color:#000"> type</span><span=
 style=3D"color:#660">&amp;</span><span style=3D"color:#000"> x</span><span=
 style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#008">throw</span><span style=3D"color:#660">()</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"=
color:#000"> </span><span style=3D"color:#800">//nonthrow since _Hasher is =
nonthrow</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span>=
<span style=3D"color:#000"> x</span><span style=3D"color:#660">.</span><spa=
n style=3D"color:#000">m_hash</span><span style=3D"color:#660">;</span><spa=
n style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </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></span><span style=
=3D"color:#660">}</span></div></code></div><div><br></div><div>I know this =
takes more space and this wrapper class should be the same size of the obje=
ct type, this is why I don&#39;t like it, but I don&#39;t see any diffrent =
solution in mind (if changing equal keys doesn&#39;t move the object I thin=
k the hash value must be saved somehow).</div><div>Now all that&#39;s left =
is to add setter functions to the iterators and change the type being sent =
to the RB tree to be one of the wrappers.</div><div><br></div><div>What do =
you think?</div></div></blockquote></div></div></blockquote></div></div>
<br>
<p><span lang=3D"EN" style=3D"font-size:7.5pt;font-family:&quot;Arial&quot;=
,&quot;sans-serif&quot;;color:#222222;background:white">This e-mail togethe=
r with
any attachments (the &quot;Message&quot;) is confidential and may contain
privileged information. If you are not the intended recipient or if you hav=
e
received this e-mail in error, please notify the sender immediately and
permanently delete this Message from your system.=C2=A0 Do not copy, disclo=
se
or distribute the information contained in this Message.</span></p>

<p><span lang=3D"EN" style=3D"font-size:7.5pt;font-family:&quot;Arial&quot;=
,&quot;sans-serif&quot;;color:#222222;background:white">=C2=A0</span></p>

<p><span lang=3D"EN" style=3D"font-size:7.5pt;font-family:&quot;Arial&quot;=
,&quot;sans-serif&quot;;color:#222222;background:white">Maven Securities Ho=
lding
Ltd (No. 07505438), Maven Trading Ltd (No. 07511928), Maven Derivatives Ltd
(No. 07511840) &amp; Maven Europe Ltd (No. 08966593) are registered as
companies in England and their registered office address is Camomile Court,=
 23
Camomile St London EC3A 7LL, United Kingdom and their VAT No. is 135539016.
Maven Derivatives Ltd only is authorised and regulated by the Financial Con=
duct
Authority (FRN 607267).</span></p>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; 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_6151_641019297.1436960966169--

.


Author: Omer Rosler <omer.rosler@gmail.com>
Date: Wed, 15 Jul 2015 05:44:04 -0700 (PDT)
Raw View
------=_Part_435_2073668775.1436964244582
Content-Type: multipart/alternative;
 boundary="----=_Part_436_235492742.1436964244583"

------=_Part_436_235492742.1436964244583
Content-Type: text/plain; charset=UTF-8

First, Thanks for the feedback.
The reason I used the default value of the Comparator to be std::equal_to
is because I wanted this class to be a stand-alone, regardless of
containers; containers will use it with !comp(lhs, rhs) && !comp(rhs, lhs) instead
of this default value as you mentionted.
I did not know about the mutable keyword, this simplifies things alot, so
thank you for that.
About the unordered containers: I don't want to define a new hash function
every time I use an unordered container with this type, although I can't
see a solution that doesn't take more memory (or any possible way of making
a template hasher that performs a hash on a representative for general type
and general comparator).
If a limited access wrapper like this is a common nescessity (beyond
mutable keys in associative containers) then maybe it is worth standarizing
on it's own.
If so, the comparator needs not to come from a container, so using a static
member is probably the solution.
So, is this limited access wrapper worth standarizing?

On Tuesday, July 14, 2015 at 11:23:45 PM UTC+3, Omer Rosler wrote:
>
> This is the first time I share my ideas about C++, so don't be too harsh :)
> This post is an attempt to partially solve the problem of key replacement
>  in (unordered) associative containers such as
> (unordered_)(multi)map, (unordered_)(multi)set* when the object doesn't
> move inside the container after replacement and the value *up to the
> comparator* is the same.
> *The braces () mean optiopnal.
> Note that in ordered containers if the value doesn't change (up to the
> comparator) so does the position of the object; in unordered this gets
> trickier, but we'll get to that later.
> My aproach is to create an intermediate class that provides a const-like
> access to a object but allows changing it if a comparator yields true (so
> the complexity of the assignment operator is the maximum of the complexity
> of the object type's assignemnt operator, and the comparator's complexity).
> In case of setting a diffrent value this class can either throw some
> exception or simply do nothing (up for debate).
> By using this class inside the underlying RB tree as the value type
> (instead of a simple const type) it will allow iterators to change the
> value of the key they hold by calling the wrapper class's assignemnt
> iterator.
> I haven't decided whether it's smart to make this class public and change
> the containers' value type (meaning: big diffrence from older versions for
> all 8 containers, although the conversion operator makes old code work all
> the same), or simply make it private and convert to container's value type
> inside the iterators which will now have setter functions.
> The second option has major downsides: The current iterators interface
> needs to be changed, instead of holding const key as a public member (like
> it does now), it will hold this wrapper class as a private/protected
> member, and accessing it must be done using a function call to a getter
> that calls a conversion operator (so access is using funtion calls only,
> instead of accessing a public member):
> template<class Key_type, Compare Comparator = std::equal_to<Key_type> >
> struct iterator {
>         //other code...
>         const Key_type& key() const { //getter
>                 return m_value; //call conversion operator
>         }
>         const Key_type& key(const Key_type&x) { //setter
>                 return m_value = x; //call copy assignment operator of
> wrapper class
>         }
> private:
>         const_to_comparison<Key_type, Comparator> m_value
> };
>
> (The name 'key' isn't the real function name, for map iterator it will be
> 'first', and for the set iterator it will be operator* for getter and set
> (maybe not a good name in this case) for setter)
> It is possible to be made compatible with other versions but will make the
> container to hold another public member for the converted type which takes
> twice the memory it used to.
> So maybe the first option where this wrapper class is public is better (at
> least in my opinion).
> Maybe there are other places this const-like access can be used.
> Well, the wrapper looks basically like this:
>
> namespace std {
> template<class _Kty, Compare _Pr = std::equal_to<_Kty> >
> class const_to_comparison {
>         typedef const_to_comparison<_Kty, _Pr> _Myt;
>         typedef _Kty key_type;
>         typedef _Pr key_compare;
>         static const key_compare comp = _Pr();
> public:
>         constexpr const_to_comparison() = default;
>         constexpr const_to_comparison(const key_type& key) : m_value(key)
> {}
>         constexpr const_to_comparison(const _Myt& other) : m_value(other.
> key) {}
>         constexpr const_to_comparison(const _Myt&& other) : m_value(other.
> key) {}
>                 _Myt& operator=(const_to_comparison&& other) {
>                 if (!comp(m_value, other.m_value))
>                          std::bad_exception("can't change this value"); //colud
> be any other exception or simply do nothing
>                 m_value = other.m_value; //calling move operator=
>         }
>         _Myt& operator=(const_to_comparison& other) {
>                 if (!comp(m_value, other.m_value))
>                          std::bad_exception("can't change this value"); //colud
> be any other exception or simply do nothing
>                 m_value = other.m_value; //calling copy operator=
>         }
>         operator const _Kty&() { //for casting to the container's
> value_type inside the iterator
>                 return m_value;
>         }
>         ~const_to_comparison() = default;
> private:
>         key_type m_value;
> };
> }
>
> For unordered containers this obviously wouldn't work since the hash value
> would change every time the key changes and so will the position in the
> container, and this whole mechanism will fail.
> Therefore the hash value must remain constant after equal key replacement,
> so I tried to solve it the simplest way I could think of (I don't really
> like this solution so feel free to rip it to shreds):
> Save the hash value of the original object in another field and overload
> std::hash of this wrapper class to return this field.
> Something like this:
>
> namespace std {
> template<class _Kty, Compare _Pr = std::equal_to<_Kty>, Hash _Hasher = std
> ::hash<_Kty> >
> class const_to_comparison_and_hash_value : public const_to_comparison <
> _Kty, _Pr > {
>         typedef const_to_comparison< _Kty, _Pr> _Mybase;
>         typedef const_to_comparison_and_hash_value<_Kty, _Pr, _Hasher>
> _Myt;
>         typedef _Kty key_type;
>         typedef _Pr key_compare;
>         typedef _Hasher key_hash;
>         static const key_hash hash = _Hasher();
> public:
>         constexpr const_to_comparison_and_hash_value() : _Mybase() {}
>         constexpr const_to_comparison_and_hash_value(const key_type& other
> ) : _Mybase(other) {}
>         constexpr const_to_comparison_and_hash_value(const _Mybase& other)
> : _Mybase(other) {}
>         constexpr const_to_comparison_and_hash_value(const _Myt& other) :
> _Mybase(other) {}
>         constexpr const_to_comparison_and_hash_value(const _Myt&& other) :
> _Mybase(other) {}
>         _Myt& operator=(const _Myt& other) {
>                 this->_Mybase::operator=((const _Mybase&)other);
>         }
>         _Myt& operator=(const _Myt&& other) {
>                this
> ...

--

---
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_436_235492742.1436964244583
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">First, Thanks for the feedback.<div>The reason I used the =
default value of the Comparator to be std::equal_to is because I wanted thi=
s class to be a stand-alone, regardless of containers; containers will use =
it with=C2=A0<span style=3D"font-family: &#39;courier new&#39;, monospace;"=
>!comp(lhs, rhs) &amp;&amp; !comp(rhs, lhs)</span>=C2=A0instead of this def=
ault value as you mentionted.</div><div>I did not know about the mutable ke=
yword, this simplifies things alot, so thank you for that.</div><div>About =
the unordered containers: I don&#39;t want to define a new hash function ev=
ery time I use an unordered container with this type, although I can&#39;t =
see a solution that doesn&#39;t take more memory (or any possible way of ma=
king a template hasher that performs a hash on a representative for general=
 type and general comparator).</div><div>If a limited access wrapper like t=
his is a common nescessity (beyond mutable keys in associative containers) =
then maybe it is worth standarizing on it&#39;s own.</div><div>If so, the c=
omparator needs not to come from a container, so using a static member is p=
robably the solution.</div><div>So, is this limited access wrapper worth st=
andarizing?<br><br>On Tuesday, July 14, 2015 at 11:23:45 PM UTC+3, Omer Ros=
ler 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"><di=
v>This is the first time I share my ideas about C++, so don&#39;t be too ha=
rsh :)<br></div><div>This post is an attempt to partially solve the problem=
 of key replacement =C2=A0in (unordered) associative containers such as</di=
v><div>(unordered_)(multi)map, (unordered_)(multi)set* when the object does=
n&#39;t move inside the container after replacement and the value <b>up to =
the comparator</b> is the same.</div><div>*The braces () mean optiopnal.</d=
iv><div>Note that in ordered containers if the value doesn&#39;t change (up=
 to the comparator) so does the position of the object; in unordered this g=
ets trickier, but we&#39;ll get to that later.</div><div>My aproach is to c=
reate an intermediate class that provides a const-like access to a object b=
ut allows changing it if a comparator yields true (so the complexity of the=
 assignment operator is the maximum of the complexity of the object type&#3=
9;s assignemnt operator, and the comparator&#39;s complexity).</div><div>In=
 case of setting a diffrent value this class can either throw some exceptio=
n or simply do nothing (up for debate).</div><div>By using this class insid=
e the underlying RB tree as the value type (instead of a simple const type)=
 it will allow iterators to change the value of the key they hold by callin=
g the wrapper class&#39;s assignemnt iterator.</div><div>I haven&#39;t deci=
ded whether it&#39;s smart to make this class public and change the contain=
ers&#39; value type (meaning: big diffrence from older versions for all 8 c=
ontainers, although the conversion operator makes old code work all the sam=
e), or simply make it private and convert to container&#39;s value type ins=
ide the iterators which will now have setter functions.</div><div>The secon=
d option has major downsides: The current iterators interface needs to be c=
hanged, instead of holding const key as a public member (like it does now),=
 it will hold this wrapper class as a private/protected member, and accessi=
ng it must be done using a function call to a getter that calls a conversio=
n operator (so access is using funtion calls only, instead of accessing a p=
ublic member):</div><div><div style=3D"border:1px solid rgb(187,187,187);wo=
rd-wrap:break-word;background-color:rgb(250,250,250)"><code><div><span styl=
e=3D"color:#008">template</span><span style=3D"color:#660">&lt;</span><span=
 style=3D"color:#008">class</span><span style=3D"color:#000"> </span><span =
style=3D"color:#606">Key_type</span><span style=3D"color:#660">,</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#606">Compare</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#606">Comparator</span=
><span style=3D"color:#000"> </span><span style=3D"color:#660">=3D</span><s=
pan style=3D"color:#000"> std</span><span style=3D"color:#660">::</span><sp=
an style=3D"color:#000">equal_to</span><span style=3D"color:#660">&lt;</spa=
n><span style=3D"color:#606">Key_type</span><span style=3D"color:#660">&gt;=
</span><span style=3D"color:#000"> </span><span style=3D"color:#660">&gt;</=
span><span style=3D"color:#000"><br></span><span style=3D"color:#008">struc=
t</span><span style=3D"color:#000"> iterator </span><span style=3D"color:#6=
60">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </sp=
an><span style=3D"color:#800">//other code...</span><span style=3D"color:#0=
00"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">const=
</span><span style=3D"color:#000"> </span><span style=3D"color:#606">Key_ty=
pe</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#000">=
 key</span><span style=3D"color:#660">()</span><span style=3D"color:#000"> =
</span><span style=3D"color:#008">const</span><font color=3D"#666600"><span=
 style=3D"color:#000"> </span><span style=3D"color:#660">{</span></font><sp=
an style=3D"color:#000"> </span><span style=3D"color:#800">//getter</span><=
span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 </span><span style=3D"color:#008">return</span><span style=3D"co=
lor:#000"> m_value</span><span style=3D"color:#660">;</span><span style=3D"=
color:#000"> </span><span style=3D"color:#800">//</span><font color=3D"#000=
000"><span style=3D"color:#800">call conversion operator</span><span style=
=3D"color:#000"><br></span></font><span style=3D"color:#000">=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span style=3D"colo=
r:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">c=
onst</span><span style=3D"color:#000"> </span><span style=3D"color:#606">Ke=
y_type</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#0=
00"> key</span><span style=3D"color:#660">(</span><span style=3D"color:#008=
">const</span><span style=3D"color:#000"> </span><span style=3D"color:#606"=
>Key_type</span><span style=3D"color:#660">&amp;</span><span style=3D"color=
:#000">x</span><span style=3D"color:#660">)</span><span style=3D"color:#000=
"> </span><span style=3D"color:#660">{</span><span style=3D"color:#000"> </=
span><span style=3D"color:#800">//setter</span><span style=3D"color:#000"><=
br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span sty=
le=3D"color:#008">return</span><span style=3D"color:#000"> m_value </span><=
span style=3D"color:#660">=3D</span><span style=3D"color:#000"> x</span><sp=
an style=3D"color:#660">;</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#800">//call copy assignment operator of wrapper class</span><=
span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span styl=
e=3D"color:#660">}</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#008">private</span><span style=3D"color:#660">:</span><span styl=
e=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 const_to_comparison</span>=
<span style=3D"color:#660">&lt;</span><span style=3D"color:#606">Key_type</=
span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#606">Comparator</span><span style=3D"color:#660">&gt;=
</span><span style=3D"color:#000"> m_value<br></span><span style=3D"color:#=
660">};</span><font color=3D"#666600"></font></div></code></div></div><div>=
<br></div><div>(The name &#39;key&#39; isn&#39;t the real function name, fo=
r map iterator it will be &#39;first&#39;, and for the set iterator it will=
 be operator* for getter and set (maybe not a good name in this case) for s=
etter)</div><div>It is possible to be made compatible with other versions b=
ut will make the container to hold another public member for the converted =
type which takes twice the memory it used to.</div><div>So maybe the first =
option where this wrapper class is public is better (at least in my opinion=
).</div><div>Maybe there are other places this const-like access can be use=
d.</div><div>Well, the wrapper looks basically like this:</div><div><br></d=
iv><div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;bac=
kground-color:rgb(250,250,250)"><code><div><span style=3D"color:#008">names=
pace</span><span style=3D"color:#000"> std </span><span style=3D"color:#660=
">{</span><span style=3D"color:#000"><br></span><span style=3D"color:#008">=
template</span><span style=3D"color:#660">&lt;</span><span style=3D"color:#=
008">class</span><span style=3D"color:#000"> _Kty</span><span style=3D"colo=
r:#660">,</span><span style=3D"color:#000"> </span><span style=3D"color:#60=
6">Compare</span><span style=3D"color:#000"> _Pr </span><span style=3D"colo=
r:#660">=3D</span><span style=3D"color:#000"> std</span><span style=3D"colo=
r:#660">::</span><span style=3D"color:#000">equal_to</span><span style=3D"c=
olor:#660">&lt;</span><span style=3D"color:#000">_Kty</span><span style=3D"=
color:#660">&gt;</span><span style=3D"color:#000"> </span><span style=3D"co=
lor:#660">&gt;</span><span style=3D"color:#000"><br></span><span style=3D"c=
olor:#008">class</span><span style=3D"color:#000"> const_to_comparison </sp=
an><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0=
 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typedef</span><span=
 style=3D"color:#000"> const_to_comparison</span><span style=3D"color:#660"=
>&lt;</span><span style=3D"color:#000">_Kty</span><span style=3D"color:#660=
">,</span><span style=3D"color:#000"> _Pr</span><span style=3D"color:#660">=
&gt;</span><span style=3D"color:#000"> _Myt</span><span style=3D"color:#660=
">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span=
><span style=3D"color:#008">typedef</span><span style=3D"color:#000"> _Kty =
key_type</span><span style=3D"color:#660">;</span><span style=3D"color:#000=
"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typedef=
</span><span style=3D"color:#000"> _Pr key_compare</span><span style=3D"col=
or:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0=
 </span><span style=3D"color:#008">static</span><span style=3D"color:#000">=
 </span><span style=3D"color:#008">const</span><span style=3D"color:#000"> =
key_compare comp </span><span style=3D"color:#660">=3D</span><span style=3D=
"color:#000"> _Pr</span><span style=3D"color:#660">();</span><span style=3D=
"color:#000"><br></span><span style=3D"color:#008">public</span><span style=
=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0=
 =C2=A0 </span><span style=3D"color:#008">constexpr</span><span style=3D"co=
lor:#000"> const_to_comparison</span><span style=3D"color:#660">()</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#660">=3D</span><span=
 style=3D"color:#000"> </span><span style=3D"color:#008">default</span><spa=
n style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0=
 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</span><span styl=
e=3D"color:#000"> const_to_comparison</span><span style=3D"color:#660">(</s=
pan><span style=3D"color:#008">const</span><span style=3D"color:#000"> key_=
type</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#000=
"> key</span><span style=3D"color:#660">)</span><span style=3D"color:#000">=
 </span><span style=3D"color:#660">:</span><span style=3D"color:#000"> m_va=
lue</span><span style=3D"color:#660">(</span><span style=3D"color:#000">key=
</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#660">{}</span><span style=3D"color:#000"><br>=C2=A0=
 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</span><sp=
an style=3D"color:#000"> const_to_comparison</span><span style=3D"color:#66=
0">(</span><span style=3D"color:#008">const</span><span style=3D"color:#000=
"> _Myt</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#=
000"> other</span><span style=3D"color:#660">)</span><span style=3D"color:#=
000"> </span><span style=3D"color:#660">:</span><span style=3D"color:#000">=
 m_value</span><span style=3D"color:#660">(</span><span style=3D"color:#000=
">other</span><span style=3D"color:#660">.</span><span style=3D"color:#000"=
>key</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>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</sp=
an><span style=3D"color:#000"> const_to_comparison</span><span style=3D"col=
or:#660">(</span><span style=3D"color:#008">const</span><span style=3D"colo=
r:#000"> _Myt</span><span style=3D"color:#660">&amp;&amp;</span><span style=
=3D"color:#000"> other</span><span style=3D"color:#660">)</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">:</span><span style=3D"c=
olor:#000"> m_value</span><span style=3D"color:#660">(</span><span style=3D=
"color:#000">other</span><span style=3D"color:#660">.</span><span style=3D"=
color:#000">key</span><span style=3D"color:#660">)</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#660">{}</span><span style=3D"color:#=
000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</span=
><span style=3D"color:#660">&amp;</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#008">operator</span><span style=3D"color:#660">=3D(</=
span><span style=3D"color:#000">const_to_comparison</span><span style=3D"co=
lor:#660">&amp;&amp;</span><span style=3D"color:#000"> other</span><span st=
yle=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0=
 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">if</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#660">(!</span>=
<span style=3D"color:#000">comp</span><span style=3D"color:#660">(</span><s=
pan style=3D"color:#000">m_value</span><span style=3D"color:#660">,</span><=
span style=3D"color:#000"> other</span><span style=3D"color:#660">.</span><=
span style=3D"color:#000">m_value</span><span style=3D"color:#660">))</span=
><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0std</span><span style=3D"co=
lor:#660">::</span><span style=3D"color:#000">bad_exception</span><span sty=
le=3D"color:#660">(</span><span style=3D"color:#080">&quot;can&#39;t change=
 this value&quot;</span><span style=3D"color:#660">);</span><span style=3D"=
color:#000"> </span><span style=3D"color:#800">//colud be any other excepti=
on or simply do nothing</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 m_value </span><span style=3D"col=
or:#660">=3D</span><span style=3D"color:#000"> other</span><span style=3D"c=
olor:#660">.</span><span style=3D"color:#000">m_value</span><span style=3D"=
color:#660">;</span><span style=3D"color:#000"> </span><span style=3D"color=
:#800">//calling move operator=3D</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span st=
yle=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</span><span style=
=3D"color:#660">&amp;</span><span style=3D"color:#000"> </span><span style=
=3D"color:#008">operator</span><span style=3D"color:#660">=3D(</span><span =
style=3D"color:#000">const_to_comparison</span><span style=3D"color:#660">&=
amp;</span><span style=3D"color:#000"> other</span><span style=3D"color:#66=
0">)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{<=
/span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">if</span><span style=3D=
"color:#000"> </span><span style=3D"color:#660">(!</span><span style=3D"col=
or:#000">comp</span><span style=3D"color:#660">(</span><span style=3D"color=
:#000">m_value</span><span style=3D"color:#660">,</span><span style=3D"colo=
r:#000"> other</span><span style=3D"color:#660">.</span><span style=3D"colo=
r:#000">m_value</span><span style=3D"color:#660">))</span><span style=3D"co=
lor:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0std</span><span style=3D"color:#660">::</spa=
n><span style=3D"color:#000">bad_exception</span><span style=3D"color:#660"=
>(</span><span style=3D"color:#080">&quot;can&#39;t change this value&quot;=
</span><span style=3D"color:#660">);</span><span style=3D"color:#000"> </sp=
an><span style=3D"color:#800">//colud be any other exception or simply do n=
othing</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 m_value </span><span style=3D"color:#660">=3D</spa=
n><span style=3D"color:#000"> other</span><span style=3D"color:#660">.</spa=
n><span style=3D"color:#000">m_value</span><span style=3D"color:#660">;</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#800">//calling =
copy operator=3D</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color:#660">}</span><span style=3D"color:#000"=
><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">operator=
</span><span style=3D"color:#000"> </span><span style=3D"color:#008">const<=
/span><span style=3D"color:#000"> _Kty</span><span style=3D"color:#660">&am=
p;()</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{<=
/span><span style=3D"color:#000"> </span><span style=3D"color:#800">//for c=
asting to the container&#39;s value_type inside the iterator</span><span st=
yle=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 </span><span style=3D"color:#008">return</span><span style=3D"color:#00=
0"> m_value</span><span style=3D"color:#660">;</span><span style=3D"color:#=
000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660">}</s=
pan><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span=
 style=3D"color:#660">~</span><span style=3D"color:#000">const_to_compariso=
n</span><span style=3D"color:#660">()</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> </span=
><span style=3D"color:#008">default</span><span style=3D"color:#660">;</spa=
n><span style=3D"color:#000"><br></span><span style=3D"color:#008">private<=
/span><span style=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 key_type m_value</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></span><span style=3D"color:#660">}</=
span></div></code></div><div style=3D"font-family:monospace;background-colo=
r:rgb(250,250,250)"><br></div><div>For unordered containers this obviously =
wouldn&#39;t work since the hash value would change every time the key chan=
ges and so will the position in the container, and this whole mechanism wil=
l fail.</div><div>Therefore the hash value must remain constant after equal=
 key replacement, so I tried to solve it the simplest way I could think of =
(I don&#39;t really like this solution so feel free to rip it to shreds):</=
div><div>Save the hash value of the original object in another field and ov=
erload std::hash of this wrapper class to return this field.</div><div>Some=
thing like this:</div><div style=3D"border:1px solid rgb(187,187,187);word-=
wrap:break-word;background-color:rgb(250,250,250)"><code><div><span style=
=3D"color:#000"><br></span><span style=3D"color:#008">namespace</span><span=
 style=3D"color:#000"> std </span><span style=3D"color:#660">{</span><span =
style=3D"color:#000"><br></span><span style=3D"color:#008">template</span><=
span style=3D"color:#660">&lt;</span><span style=3D"color:#008">class</span=
><span style=3D"color:#000"> _Kty</span><span style=3D"color:#660">,</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#606">Compare</span=
><span style=3D"color:#000"> _Pr </span><span style=3D"color:#660">=3D</spa=
n><span style=3D"color:#000"> std</span><span style=3D"color:#660">::</span=
><span style=3D"color:#000">equal_to</span><span style=3D"color:#660">&lt;<=
/span><span style=3D"color:#000">_Kty</span><span style=3D"color:#660">&gt;=
,</span><span style=3D"color:#000"> </span><span style=3D"color:#606">Hash<=
/span><span style=3D"color:#000"> _Hasher </span><span style=3D"color:#660"=
>=3D</span><span style=3D"color:#000"> std</span><span style=3D"color:#660"=
>::</span><span style=3D"color:#000">hash</span><span style=3D"color:#660">=
&lt;</span><span style=3D"color:#000">_Kty</span><span style=3D"color:#660"=
>&gt;</span><span style=3D"color:#000"> </span><span style=3D"color:#660">&=
gt;</span><span style=3D"color:#000"><br></span><span style=3D"color:#008">=
class</span><span style=3D"color:#000"> const_to_comparison_and_hash_value =
</span><span style=3D"color:#660">:</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#008">public</span><span style=3D"color:#000"> const=
_to_comparison </span><span style=3D"color:#660">&lt;</span><span style=3D"=
color:#000"> _Kty</span><span style=3D"color:#660">,</span><span style=3D"c=
olor:#000"> _Pr </span><span style=3D"color:#660">&gt;</span><span style=3D=
"color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"colo=
r:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">t=
ypedef</span><span style=3D"color:#000"> const_to_comparison</span><span st=
yle=3D"color:#660">&lt;</span><span style=3D"color:#000"> _Kty</span><span =
style=3D"color:#660">,</span><span style=3D"color:#000"> _Pr</span><span st=
yle=3D"color:#660">&gt;</span><span style=3D"color:#000"> _Mybase</span><sp=
an style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typedef</span><span sty=
le=3D"color:#000"> const_to_comparison_and_hash_value</span><span style=3D"=
color:#660">&lt;</span><span style=3D"color:#000">_Kty</span><span style=3D=
"color:#660">,</span><span style=3D"color:#000"> _Pr</span><span style=3D"c=
olor:#660">,</span><span style=3D"color:#000"> _Hasher</span><span style=3D=
"color:#660">&gt;</span><span style=3D"color:#000"> _Myt</span><span style=
=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0=
 =C2=A0 </span><span style=3D"color:#008">typedef</span><span style=3D"colo=
r:#000"> _Kty key_type</span><span style=3D"color:#660">;</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color=
:#008">typedef</span><span style=3D"color:#000"> _Pr key_compare</span><spa=
n style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0=
 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typedef</span><span style=
=3D"color:#000"> _Hasher key_hash</span><span style=3D"color:#660">;</span>=
<span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span sty=
le=3D"color:#008">static</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#008">const</span><span style=3D"color:#000"> key_hash hash </s=
pan><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> _Hashe=
r</span><span style=3D"color:#660">();</span><span style=3D"color:#000"><br=
></span><span style=3D"color:#008">public</span><span style=3D"color:#660">=
:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><=
span style=3D"color:#008">constexpr</span><span style=3D"color:#000"> const=
_to_comparison_and_hash_value</span><span style=3D"color:#660">()</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#660">:</span><span st=
yle=3D"color:#000"> _Mybase</span><span style=3D"color:#660">()</span><span=
 style=3D"color:#000"> </span><span style=3D"color:#660">{}</span><span sty=
le=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"col=
or:#008">constexpr</span><span style=3D"color:#000"> const_to_comparison_an=
d_hash_value</span><span style=3D"color:#660">(</span><span style=3D"color:=
#008">const</span><span style=3D"color:#000"> key_type</span><span style=3D=
"color:#660">&amp;</span><span style=3D"color:#000"> other</span><span styl=
e=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"=
color:#660">:</span><span style=3D"color:#000"> _Mybase</span><span style=
=3D"color:#660">(</span><span style=3D"color:#000">other</span><span style=
=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#660">{}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 </span><span style=3D"color:#008">constexpr</span><span style=3D"color:=
#000"> const_to_comparison_and_hash_value</span><span style=3D"color:#660">=
(</span><span style=3D"color:#008">const</span><span style=3D"color:#000"> =
_Mybase</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#=
000"> other</span><span style=3D"color:#660">)</span><span style=3D"color:#=
000"> </span><span style=3D"color:#660">:</span><span style=3D"color:#000">=
 _Mybase</span><span style=3D"color:#660">(</span><span style=3D"color:#000=
">other</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=
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</s=
pan><span style=3D"color:#000"> const_to_comparison_and_hash_value</span><s=
pan style=3D"color:#660">(</span><span style=3D"color:#008">const</span><sp=
an style=3D"color:#000"> _Myt</span><span style=3D"color:#660">&amp;</span>=
<span style=3D"color:#000"> other</span><span style=3D"color:#660">)</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#660">:</span><span=
 style=3D"color:#000"> _Mybase</span><span style=3D"color:#660">(</span><sp=
an style=3D"color:#000">other</span><span style=3D"color:#660">)</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#660">{}</span><span st=
yle=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"co=
lor:#008">constexpr</span><span style=3D"color:#000"> const_to_comparison_a=
nd_hash_value</span><span style=3D"color:#660">(</span><span style=3D"color=
:#008">const</span><span style=3D"color:#000"> _Myt</span><span style=3D"co=
lor:#660">&amp;&amp;</span><span style=3D"color:#000"> other</span><span st=
yle=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">:</span><span style=3D"color:#000"> _Mybase</span><span sty=
le=3D"color:#660">(</span><span style=3D"color:#000">other</span><span styl=
e=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"=
color:#660">{}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 _Myt</span><span style=3D"color:#660">&amp;</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#008">operator</span><span style=3D"c=
olor:#660">=3D(</span><span style=3D"color:#008">const</span><span style=3D=
"color:#000"> _Myt</span><span style=3D"color:#660">&amp;</span><span style=
=3D"color:#000"> other</span><span style=3D"color:#660">)</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"c=
olor:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </sp=
an><span style=3D"color:#008">this</span><span style=3D"color:#660">-&gt;</=
span><span style=3D"color:#000">_Mybase</span><span style=3D"color:#660">::=
</span><span style=3D"color:#008">operator</span><span style=3D"color:#660"=
>=3D((</span><span style=3D"color:#008">const</span><span style=3D"color:#0=
00"> _Mybase</span><span style=3D"color:#660">&amp;)</span><span style=3D"c=
olor:#000">other</span><span style=3D"color:#660">);</span><span style=3D"c=
olor:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660=
">}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</=
span><span style=3D"color:#660">&amp;</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#008">operator</span><span style=3D"color:#660">=
=3D(</span><span style=3D"color:#008">const</span><span style=3D"color:#000=
"> _Myt</span><span style=3D"color:#660">&amp;&amp;</span><span style=3D"co=
lor:#000"> other</span><span style=3D"color:#660">)</span><span style=3D"co=
lor:#000"> </span><span style=3D"color:#660">{</span><span style=3D"color:#=
000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><spa=
n style=3D"color:#008">this</span></div></code></div></div>...</blockquote>=
</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&quot; 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_436_235492742.1436964244583--
------=_Part_435_2073668775.1436964244582--

.


Author: Edward Catmur <ed@catmur.co.uk>
Date: Wed, 15 Jul 2015 06:50:26 -0700 (PDT)
Raw View
------=_Part_168_996300156.1436968227035
Content-Type: multipart/alternative;
 boundary="----=_Part_169_198855859.1436968227037"

------=_Part_169_198855859.1436968227037
Content-Type: text/plain; charset=UTF-8

On Wednesday, 15 July 2015 13:44:04 UTC+1, Omer Rosler wrote:
>
> First, Thanks for the feedback.
> The reason I used the default value of the Comparator to be std::equal_to
> is because I wanted this class to be a stand-alone, regardless of
> containers; containers will use it with !comp(lhs, rhs) && !comp(rhs, lhs) instead
> of this default value as you mentionted.
> I did not know about the mutable keyword, this simplifies things alot, so
> thank you for that.
> About the unordered containers: I don't want to define a new hash function
> every time I use an unordered container with this type, although I can't
> see a solution that doesn't take more memory (or any possible way of making
> a template hasher that performs a hash on a representative for general type
> and general comparator).
>

Why not just use the hash on the underlying type?


> If a limited access wrapper like this is a common nescessity (beyond
> mutable keys in associative containers) then maybe it is worth standarizing
> on it's own.
> If so, the comparator needs not to come from a container, so using a
> static member is probably the solution.
>

The problem there is that hashers can have state (e.g. a function pointer
or a type-erased function wrapper), so a static member won't work. I can't
think of any use other than associative containers, so you might as well
use the container's comparator and hasher.


> So, is this limited access wrapper worth standarizing?
>
> On Tuesday, July 14, 2015 at 11:23:45 PM UTC+3, Omer Rosler wrote:
>>
>> This is the first time I share my ideas about C++, so don't be too harsh
>> :)
>> This post is an attempt to partially solve the problem of key replacement
>>  in (unordered) associative containers such as
>> (unordered_)(multi)map, (unordered_)(multi)set* when the object doesn't
>> move inside the container after replacement and the value *up to the
>> comparator* is the same.
>> *The braces () mean optiopnal.
>> Note that in ordered containers if the value doesn't change (up to the
>> comparator) so does the position of the object; in unordered this gets
>> trickier, but we'll get to that later.
>> My aproach is to create an intermediate class that provides a const-like
>> access to a object but allows changing it if a comparator yields true (so
>> the complexity of the assignment operator is the maximum of the complexity
>> of the object type's assignemnt operator, and the comparator's complexity).
>> In case of setting a diffrent value this class can either throw some
>> exception or simply do nothing (up for debate).
>> By using this class inside the underlying RB tree as the value type
>> (instead of a simple const type) it will allow iterators to change the
>> value of the key they hold by calling the wrapper class's assignemnt
>> iterator.
>> I haven't decided whether it's smart to make this class public and change
>> the containers' value type (meaning: big diffrence from older versions for
>> all 8 containers, although the conversion operator makes old code work all
>> the same), or simply make it private and convert to container's value type
>> inside the iterators which will now have setter functions.
>> The second option has major downsides: The current iterators interface
>> needs to be changed, instead of holding const key as a public member (like
>> it does now), it will hold this wrapper class as a private/protected
>> member, and accessing it must be done using a function call to a getter
>> that calls a conversion operator (so access is using funtion calls only,
>> instead of accessing a public member):
>> template<class Key_type, Compare Comparator = std::equal_to<Key_type> >
>> struct iterator {
>>         //other code...
>>         const Key_type& key() const { //getter
>>                 return m_value; //call conversion operator
>>         }
>>         const Key_type& key(const Key_type&x) { //setter
>>                 return m_value = x; //call copy assignment operator of
>> wrapper class
>>         }
>> private:
>>         const_to_comparison<Key_type, Comparator> m_value
>> };
>>
>> (The name 'key' isn't the real function name, for map iterator it will be
>> 'first', and for the set iterator it will be operator* for getter and set
>> (maybe not a good name in this case) for setter)
>> It is possible to be made compatible with other versions but will make
>> the container to hold another public member for the converted type which
>> takes twice the memory it used to.
>> So maybe the first option where this wrapper class is public is better
>> (at least in my opinion).
>> Maybe there are other places this const-like access can be used.
>> Well, the wrapper looks basically like this:
>>
>> namespace std {
>> template<class _Kty, Compare _Pr = std::equal_to<_Kty> >
>> class const_to_comparison {
>>         typedef const_to_comparison<_Kty, _Pr> _Myt;
>>         typedef _Kty key_type;
>>         typedef _Pr key_compare;
>>         static const key_compare comp = _Pr();
>> public:
>>         constexpr const_to_comparison() = default;
>>         constexpr const_to_comparison(const key_type& key) : m_value(key)
>> {}
>>         constexpr const_to_comparison(const _Myt& other) : m_value(other.
>> key) {}
>>         constexpr const_to_comparison(const _Myt&& other) : m_value(other
>> .key) {}
>>                 _Myt& operator=(const_to_comparison&& other) {
>>                 if (!comp(m_value, other.m_value))
>>                          std::bad_exception("can't change this value"); //colud
>> be any other exception or simply do nothing
>>                 m_value = other.m_value; //calling move operator=
>>         }
>>         _Myt& operator=(const_to_comparison& other) {
>>                 if (!comp(m_value, other.m_value))
>>                          std::bad_exception("can't change this value"); //colud
>> be any other exception or simply do nothing
>>                 m_value = other.m_value; //calling copy operator=
>>         }
>>         operator const _Kty&() { //for casting to the container's
>> value_type inside the iterator
>>                 return m_value;
>>         }
>>         ~const_to_comparison() = default;
>> private:
>>         key_type m_value;
>> };
>> }
>>
>> For unordered containers this obviously wouldn't work since the hash
>> value would change every time the key changes and so will the position in
>> the container, and this whole mechanism will fail.
>> Therefore the hash value must remain constant after equal key
>> replacement, so I tried to solve it the simplest way I could think of (I
>> don't really like this solution so feel free to rip it to shreds):
>> Save the hash value of the original object in another field and overload
>> std::hash of this wrapper class to return this field.
>> Something like this:
>>
>> namespace std {
>> template<class _Kty, Compare _Pr = std::equal_to<_Kty>, Hash _Hasher =
>> std::hash<_Kty> >
>> class const_to_comparison_and_hash_value : public const_to_comparison <
>> _Kty, _Pr > {
>>         typedef const_to_comparison< _Kty, _Pr> _Mybase;
>>         typedef const_to_comparison_and_hash_value<_Kty, _Pr, _Hasher>
>> _Myt;
>>         typedef _Kty key_type;
>>         typedef _Pr key_compare;
>>         typedef _Hasher key_hash;
>>         static const key_hash hash = _Hasher();
>> public:
>>         constexpr const_to_comparison_and_hash_value() : _Mybase() {}
>>         constexpr const_to_comparison_and_hash_value(const key_type&
>> other) : _Mybase(other) {}
>>         constexpr const_to_comparison_and_hash_value(const _Mybase& other
>> ) : _Mybase(other) {}
>>         constexpr const_to_comparison_and_hash_value(const _Myt& other) :
>> _Mybase(other) {}
>>         constexpr const_to_comparison_and_hash_value(const _Myt&& other)
>> : _Mybase(other) {}
>>         _Myt& operator=(const _Myt& other) {
>>                 this->_Mybase::operator=((const _Mybase&)other);
>>         }
>>         _Myt& operator=(const _Myt&& other) {
>>                this
>> ...
>
>

--

---
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_169_198855859.1436968227037
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

On Wednesday, 15 July 2015 13:44:04 UTC+1, Omer Rosler  wrote:<blockquote c=
lass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px=
 #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">First, Thanks for the feed=
back.<div>The reason I used the default value of the Comparator to be std::=
equal_to is because I wanted this class to be a stand-alone, regardless of =
containers; containers will use it with=C2=A0<span style=3D"font-family:&#3=
9;courier new&#39;,monospace">!comp(lhs, rhs) &amp;&amp; !comp(rhs, lhs)</s=
pan>=C2=A0instead of this default value as you mentionted.</div><div>I did =
not know about the mutable keyword, this simplifies things alot, so thank y=
ou for that.</div><div>About the unordered containers: I don&#39;t want to =
define a new hash function every time I use an unordered container with thi=
s type, although I can&#39;t see a solution that doesn&#39;t take more memo=
ry (or any possible way of making a template hasher that performs a hash on=
 a representative for general type and general comparator).</div></div></bl=
ockquote><div><br></div><div>Why not just use the hash on the underlying ty=
pe?</div><div>=C2=A0</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>If a limited access wrapper like this is a common nescess=
ity (beyond mutable keys in associative containers) then maybe it is worth =
standarizing on it&#39;s own.</div><div>If so, the comparator needs not to =
come from a container, so using a static member is probably the solution.</=
div></div></blockquote><div><br></div><div>The problem there is that hasher=
s can have state (e.g. a function pointer or a type-erased function wrapper=
), so a static member won&#39;t work. I can&#39;t think of any use other th=
an associative containers, so you might as well use the container&#39;s com=
parator and hasher.</div><div>=C2=A0</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>So, is this limited access wrapper worth =
standarizing?<br><br>On Tuesday, July 14, 2015 at 11:23:45 PM UTC+3, Omer R=
osler 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>T=
his is the first time I share my ideas about C++, so don&#39;t be too harsh=
 :)<br></div><div>This post is an attempt to partially solve the problem of=
 key replacement =C2=A0in (unordered) associative containers such as</div><=
div>(unordered_)(multi)map, (unordered_)(multi)set* when the object doesn&#=
39;t move inside the container after replacement and the value <b>up to the=
 comparator</b> is the same.</div><div>*The braces () mean optiopnal.</div>=
<div>Note that in ordered containers if the value doesn&#39;t change (up to=
 the comparator) so does the position of the object; in unordered this gets=
 trickier, but we&#39;ll get to that later.</div><div>My aproach is to crea=
te an intermediate class that provides a const-like access to a object but =
allows changing it if a comparator yields true (so the complexity of the as=
signment operator is the maximum of the complexity of the object type&#39;s=
 assignemnt operator, and the comparator&#39;s complexity).</div><div>In ca=
se of setting a diffrent value this class can either throw some exception o=
r simply do nothing (up for debate).</div><div>By using this class inside t=
he underlying RB tree as the value type (instead of a simple const type) it=
 will allow iterators to change the value of the key they hold by calling t=
he wrapper class&#39;s assignemnt iterator.</div><div>I haven&#39;t decided=
 whether it&#39;s smart to make this class public and change the containers=
&#39; value type (meaning: big diffrence from older versions for all 8 cont=
ainers, although the conversion operator makes old code work all the same),=
 or simply make it private and convert to container&#39;s value type inside=
 the iterators which will now have setter functions.</div><div>The second o=
ption has major downsides: The current iterators interface needs to be chan=
ged, instead of holding const key as a public member (like it does now), it=
 will hold this wrapper class as a private/protected member, and accessing =
it must be done using a function call to a getter that calls a conversion o=
perator (so access is using funtion calls only, instead of accessing a publ=
ic member):</div><div><div style=3D"border:1px solid rgb(187,187,187);word-=
wrap:break-word;background-color:rgb(250,250,250)"><code><div><span style=
=3D"color:#008">template</span><span style=3D"color:#660">&lt;</span><span =
style=3D"color:#008">class</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#606">Key_type</span><span style=3D"color:#660">,</span><span=
 style=3D"color:#000"> </span><span style=3D"color:#606">Compare</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#606">Comparator</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#660">=3D</span><sp=
an style=3D"color:#000"> std</span><span style=3D"color:#660">::</span><spa=
n style=3D"color:#000">equal_to</span><span style=3D"color:#660">&lt;</span=
><span style=3D"color:#606">Key_type</span><span style=3D"color:#660">&gt;<=
/span><span style=3D"color:#000"> </span><span style=3D"color:#660">&gt;</s=
pan><span style=3D"color:#000"><br></span><span style=3D"color:#008">struct=
</span><span style=3D"color:#000"> iterator </span><span style=3D"color:#66=
0">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </spa=
n><span style=3D"color:#800">//other code...</span><span style=3D"color:#00=
0"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">const<=
/span><span style=3D"color:#000"> </span><span style=3D"color:#606">Key_typ=
e</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#000"> =
key</span><span style=3D"color:#660">()</span><span style=3D"color:#000"> <=
/span><span style=3D"color:#008">const</span><font color=3D"#666600"><span =
style=3D"color:#000"> </span><span style=3D"color:#660">{</span></font><spa=
n style=3D"color:#000"> </span><span style=3D"color:#800">//getter</span><s=
pan style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 </span><span style=3D"color:#008">return</span><span style=3D"co=
lor:#000"> m_value</span><span style=3D"color:#660">;</span><span style=3D"=
color:#000"> </span><span style=3D"color:#800">//</span><font color=3D"#000=
000"><span style=3D"color:#800">call conversion operator</span><span style=
=3D"color:#000"><br></span></font><span style=3D"color:#000">=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span style=3D"colo=
r:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">c=
onst</span><span style=3D"color:#000"> </span><span style=3D"color:#606">Ke=
y_type</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#0=
00"> key</span><span style=3D"color:#660">(</span><span style=3D"color:#008=
">const</span><span style=3D"color:#000"> </span><span style=3D"color:#606"=
>Key_type</span><span style=3D"color:#660">&amp;</span><span style=3D"color=
:#000">x</span><span style=3D"color:#660">)</span><span style=3D"color:#000=
"> </span><span style=3D"color:#660">{</span><span style=3D"color:#000"> </=
span><span style=3D"color:#800">//setter</span><span style=3D"color:#000"><=
br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span sty=
le=3D"color:#008">return</span><span style=3D"color:#000"> m_value </span><=
span style=3D"color:#660">=3D</span><span style=3D"color:#000"> x</span><sp=
an style=3D"color:#660">;</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#800">//call copy assignment operator of wrapper class</span><=
span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span styl=
e=3D"color:#660">}</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#008">private</span><span style=3D"color:#660">:</span><span styl=
e=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 const_to_comparison</span>=
<span style=3D"color:#660">&lt;</span><span style=3D"color:#606">Key_type</=
span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#606">Comparator</span><span style=3D"color:#660">&gt;=
</span><span style=3D"color:#000"> m_value<br></span><span style=3D"color:#=
660">};</span><font color=3D"#666600"></font></div></code></div></div><div>=
<br></div><div>(The name &#39;key&#39; isn&#39;t the real function name, fo=
r map iterator it will be &#39;first&#39;, and for the set iterator it will=
 be operator* for getter and set (maybe not a good name in this case) for s=
etter)</div><div>It is possible to be made compatible with other versions b=
ut will make the container to hold another public member for the converted =
type which takes twice the memory it used to.</div><div>So maybe the first =
option where this wrapper class is public is better (at least in my opinion=
).</div><div>Maybe there are other places this const-like access can be use=
d.</div><div>Well, the wrapper looks basically like this:</div><div><br></d=
iv><div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;bac=
kground-color:rgb(250,250,250)"><code><div><span style=3D"color:#008">names=
pace</span><span style=3D"color:#000"> std </span><span style=3D"color:#660=
">{</span><span style=3D"color:#000"><br></span><span style=3D"color:#008">=
template</span><span style=3D"color:#660">&lt;</span><span style=3D"color:#=
008">class</span><span style=3D"color:#000"> _Kty</span><span style=3D"colo=
r:#660">,</span><span style=3D"color:#000"> </span><span style=3D"color:#60=
6">Compare</span><span style=3D"color:#000"> _Pr </span><span style=3D"colo=
r:#660">=3D</span><span style=3D"color:#000"> std</span><span style=3D"colo=
r:#660">::</span><span style=3D"color:#000">equal_to</span><span style=3D"c=
olor:#660">&lt;</span><span style=3D"color:#000">_Kty</span><span style=3D"=
color:#660">&gt;</span><span style=3D"color:#000"> </span><span style=3D"co=
lor:#660">&gt;</span><span style=3D"color:#000"><br></span><span style=3D"c=
olor:#008">class</span><span style=3D"color:#000"> const_to_comparison </sp=
an><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0=
 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typedef</span><span=
 style=3D"color:#000"> const_to_comparison</span><span style=3D"color:#660"=
>&lt;</span><span style=3D"color:#000">_Kty</span><span style=3D"color:#660=
">,</span><span style=3D"color:#000"> _Pr</span><span style=3D"color:#660">=
&gt;</span><span style=3D"color:#000"> _Myt</span><span style=3D"color:#660=
">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span=
><span style=3D"color:#008">typedef</span><span style=3D"color:#000"> _Kty =
key_type</span><span style=3D"color:#660">;</span><span style=3D"color:#000=
"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typedef=
</span><span style=3D"color:#000"> _Pr key_compare</span><span style=3D"col=
or:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0=
 </span><span style=3D"color:#008">static</span><span style=3D"color:#000">=
 </span><span style=3D"color:#008">const</span><span style=3D"color:#000"> =
key_compare comp </span><span style=3D"color:#660">=3D</span><span style=3D=
"color:#000"> _Pr</span><span style=3D"color:#660">();</span><span style=3D=
"color:#000"><br></span><span style=3D"color:#008">public</span><span style=
=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0=
 =C2=A0 </span><span style=3D"color:#008">constexpr</span><span style=3D"co=
lor:#000"> const_to_comparison</span><span style=3D"color:#660">()</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#660">=3D</span><span=
 style=3D"color:#000"> </span><span style=3D"color:#008">default</span><spa=
n style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0=
 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</span><span styl=
e=3D"color:#000"> const_to_comparison</span><span style=3D"color:#660">(</s=
pan><span style=3D"color:#008">const</span><span style=3D"color:#000"> key_=
type</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#000=
"> key</span><span style=3D"color:#660">)</span><span style=3D"color:#000">=
 </span><span style=3D"color:#660">:</span><span style=3D"color:#000"> m_va=
lue</span><span style=3D"color:#660">(</span><span style=3D"color:#000">key=
</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#660">{}</span><span style=3D"color:#000"><br>=C2=A0=
 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</span><sp=
an style=3D"color:#000"> const_to_comparison</span><span style=3D"color:#66=
0">(</span><span style=3D"color:#008">const</span><span style=3D"color:#000=
"> _Myt</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#=
000"> other</span><span style=3D"color:#660">)</span><span style=3D"color:#=
000"> </span><span style=3D"color:#660">:</span><span style=3D"color:#000">=
 m_value</span><span style=3D"color:#660">(</span><span style=3D"color:#000=
">other</span><span style=3D"color:#660">.</span><span style=3D"color:#000"=
>key</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>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</sp=
an><span style=3D"color:#000"> const_to_comparison</span><span style=3D"col=
or:#660">(</span><span style=3D"color:#008">const</span><span style=3D"colo=
r:#000"> _Myt</span><span style=3D"color:#660">&amp;&amp;</span><span style=
=3D"color:#000"> other</span><span style=3D"color:#660">)</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">:</span><span style=3D"c=
olor:#000"> m_value</span><span style=3D"color:#660">(</span><span style=3D=
"color:#000">other</span><span style=3D"color:#660">.</span><span style=3D"=
color:#000">key</span><span style=3D"color:#660">)</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#660">{}</span><span style=3D"color:#=
000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</span=
><span style=3D"color:#660">&amp;</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#008">operator</span><span style=3D"color:#660">=3D(</=
span><span style=3D"color:#000">const_to_comparison</span><span style=3D"co=
lor:#660">&amp;&amp;</span><span style=3D"color:#000"> other</span><span st=
yle=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0=
 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">if</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#660">(!</span>=
<span style=3D"color:#000">comp</span><span style=3D"color:#660">(</span><s=
pan style=3D"color:#000">m_value</span><span style=3D"color:#660">,</span><=
span style=3D"color:#000"> other</span><span style=3D"color:#660">.</span><=
span style=3D"color:#000">m_value</span><span style=3D"color:#660">))</span=
><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0std</span><span style=3D"co=
lor:#660">::</span><span style=3D"color:#000">bad_exception</span><span sty=
le=3D"color:#660">(</span><span style=3D"color:#080">&quot;can&#39;t change=
 this value&quot;</span><span style=3D"color:#660">);</span><span style=3D"=
color:#000"> </span><span style=3D"color:#800">//colud be any other excepti=
on or simply do nothing</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 m_value </span><span style=3D"col=
or:#660">=3D</span><span style=3D"color:#000"> other</span><span style=3D"c=
olor:#660">.</span><span style=3D"color:#000">m_value</span><span style=3D"=
color:#660">;</span><span style=3D"color:#000"> </span><span style=3D"color=
:#800">//calling move operator=3D</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span st=
yle=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</span><span style=
=3D"color:#660">&amp;</span><span style=3D"color:#000"> </span><span style=
=3D"color:#008">operator</span><span style=3D"color:#660">=3D(</span><span =
style=3D"color:#000">const_to_comparison</span><span style=3D"color:#660">&=
amp;</span><span style=3D"color:#000"> other</span><span style=3D"color:#66=
0">)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{<=
/span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">if</span><span style=3D=
"color:#000"> </span><span style=3D"color:#660">(!</span><span style=3D"col=
or:#000">comp</span><span style=3D"color:#660">(</span><span style=3D"color=
:#000">m_value</span><span style=3D"color:#660">,</span><span style=3D"colo=
r:#000"> other</span><span style=3D"color:#660">.</span><span style=3D"colo=
r:#000">m_value</span><span style=3D"color:#660">))</span><span style=3D"co=
lor:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0std</span><span style=3D"color:#660">::</spa=
n><span style=3D"color:#000">bad_exception</span><span style=3D"color:#660"=
>(</span><span style=3D"color:#080">&quot;can&#39;t change this value&quot;=
</span><span style=3D"color:#660">);</span><span style=3D"color:#000"> </sp=
an><span style=3D"color:#800">//colud be any other exception or simply do n=
othing</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 m_value </span><span style=3D"color:#660">=3D</spa=
n><span style=3D"color:#000"> other</span><span style=3D"color:#660">.</spa=
n><span style=3D"color:#000">m_value</span><span style=3D"color:#660">;</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#800">//calling =
copy operator=3D</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color:#660">}</span><span style=3D"color:#000"=
><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">operator=
</span><span style=3D"color:#000"> </span><span style=3D"color:#008">const<=
/span><span style=3D"color:#000"> _Kty</span><span style=3D"color:#660">&am=
p;()</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{<=
/span><span style=3D"color:#000"> </span><span style=3D"color:#800">//for c=
asting to the container&#39;s value_type inside the iterator</span><span st=
yle=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 </span><span style=3D"color:#008">return</span><span style=3D"color:#00=
0"> m_value</span><span style=3D"color:#660">;</span><span style=3D"color:#=
000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660">}</s=
pan><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span=
 style=3D"color:#660">~</span><span style=3D"color:#000">const_to_compariso=
n</span><span style=3D"color:#660">()</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> </span=
><span style=3D"color:#008">default</span><span style=3D"color:#660">;</spa=
n><span style=3D"color:#000"><br></span><span style=3D"color:#008">private<=
/span><span style=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 key_type m_value</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></span><span style=3D"color:#660">}</=
span></div></code></div><div style=3D"font-family:monospace;background-colo=
r:rgb(250,250,250)"><br></div><div>For unordered containers this obviously =
wouldn&#39;t work since the hash value would change every time the key chan=
ges and so will the position in the container, and this whole mechanism wil=
l fail.</div><div>Therefore the hash value must remain constant after equal=
 key replacement, so I tried to solve it the simplest way I could think of =
(I don&#39;t really like this solution so feel free to rip it to shreds):</=
div><div>Save the hash value of the original object in another field and ov=
erload std::hash of this wrapper class to return this field.</div><div>Some=
thing like this:</div><div style=3D"border:1px solid rgb(187,187,187);word-=
wrap:break-word;background-color:rgb(250,250,250)"><code><div><span style=
=3D"color:#000"><br></span><span style=3D"color:#008">namespace</span><span=
 style=3D"color:#000"> std </span><span style=3D"color:#660">{</span><span =
style=3D"color:#000"><br></span><span style=3D"color:#008">template</span><=
span style=3D"color:#660">&lt;</span><span style=3D"color:#008">class</span=
><span style=3D"color:#000"> _Kty</span><span style=3D"color:#660">,</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#606">Compare</span=
><span style=3D"color:#000"> _Pr </span><span style=3D"color:#660">=3D</spa=
n><span style=3D"color:#000"> std</span><span style=3D"color:#660">::</span=
><span style=3D"color:#000">equal_to</span><span style=3D"color:#660">&lt;<=
/span><span style=3D"color:#000">_Kty</span><span style=3D"color:#660">&gt;=
,</span><span style=3D"color:#000"> </span><span style=3D"color:#606">Hash<=
/span><span style=3D"color:#000"> _Hasher </span><span style=3D"color:#660"=
>=3D</span><span style=3D"color:#000"> std</span><span style=3D"color:#660"=
>::</span><span style=3D"color:#000">hash</span><span style=3D"color:#660">=
&lt;</span><span style=3D"color:#000">_Kty</span><span style=3D"color:#660"=
>&gt;</span><span style=3D"color:#000"> </span><span style=3D"color:#660">&=
gt;</span><span style=3D"color:#000"><br></span><span style=3D"color:#008">=
class</span><span style=3D"color:#000"> const_to_comparison_and_hash_value =
</span><span style=3D"color:#660">:</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#008">public</span><span style=3D"color:#000"> const=
_to_comparison </span><span style=3D"color:#660">&lt;</span><span style=3D"=
color:#000"> _Kty</span><span style=3D"color:#660">,</span><span style=3D"c=
olor:#000"> _Pr </span><span style=3D"color:#660">&gt;</span><span style=3D=
"color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"colo=
r:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">t=
ypedef</span><span style=3D"color:#000"> const_to_comparison</span><span st=
yle=3D"color:#660">&lt;</span><span style=3D"color:#000"> _Kty</span><span =
style=3D"color:#660">,</span><span style=3D"color:#000"> _Pr</span><span st=
yle=3D"color:#660">&gt;</span><span style=3D"color:#000"> _Mybase</span><sp=
an style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typedef</span><span sty=
le=3D"color:#000"> const_to_comparison_and_hash_value</span><span style=3D"=
color:#660">&lt;</span><span style=3D"color:#000">_Kty</span><span style=3D=
"color:#660">,</span><span style=3D"color:#000"> _Pr</span><span style=3D"c=
olor:#660">,</span><span style=3D"color:#000"> _Hasher</span><span style=3D=
"color:#660">&gt;</span><span style=3D"color:#000"> _Myt</span><span style=
=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0=
 =C2=A0 </span><span style=3D"color:#008">typedef</span><span style=3D"colo=
r:#000"> _Kty key_type</span><span style=3D"color:#660">;</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color=
:#008">typedef</span><span style=3D"color:#000"> _Pr key_compare</span><spa=
n style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0=
 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typedef</span><span style=
=3D"color:#000"> _Hasher key_hash</span><span style=3D"color:#660">;</span>=
<span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span sty=
le=3D"color:#008">static</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#008">const</span><span style=3D"color:#000"> key_hash hash </s=
pan><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> _Hashe=
r</span><span style=3D"color:#660">();</span><span style=3D"color:#000"><br=
></span><span style=3D"color:#008">public</span><span style=3D"color:#660">=
:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><=
span style=3D"color:#008">constexpr</span><span style=3D"color:#000"> const=
_to_comparison_and_hash_value</span><span style=3D"color:#660">()</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#660">:</span><span st=
yle=3D"color:#000"> _Mybase</span><span style=3D"color:#660">()</span><span=
 style=3D"color:#000"> </span><span style=3D"color:#660">{}</span><span sty=
le=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"col=
or:#008">constexpr</span><span style=3D"color:#000"> const_to_comparison_an=
d_hash_value</span><span style=3D"color:#660">(</span><span style=3D"color:=
#008">const</span><span style=3D"color:#000"> key_type</span><span style=3D=
"color:#660">&amp;</span><span style=3D"color:#000"> other</span><span styl=
e=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"=
color:#660">:</span><span style=3D"color:#000"> _Mybase</span><span style=
=3D"color:#660">(</span><span style=3D"color:#000">other</span><span style=
=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#660">{}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 </span><span style=3D"color:#008">constexpr</span><span style=3D"color:=
#000"> const_to_comparison_and_hash_value</span><span style=3D"color:#660">=
(</span><span style=3D"color:#008">const</span><span style=3D"color:#000"> =
_Mybase</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#=
000"> other</span><span style=3D"color:#660">)</span><span style=3D"color:#=
000"> </span><span style=3D"color:#660">:</span><span style=3D"color:#000">=
 _Mybase</span><span style=3D"color:#660">(</span><span style=3D"color:#000=
">other</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=
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</s=
pan><span style=3D"color:#000"> const_to_comparison_and_hash_value</span><s=
pan style=3D"color:#660">(</span><span style=3D"color:#008">const</span><sp=
an style=3D"color:#000"> _Myt</span><span style=3D"color:#660">&amp;</span>=
<span style=3D"color:#000"> other</span><span style=3D"color:#660">)</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#660">:</span><span=
 style=3D"color:#000"> _Mybase</span><span style=3D"color:#660">(</span><sp=
an style=3D"color:#000">other</span><span style=3D"color:#660">)</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#660">{}</span><span st=
yle=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"co=
lor:#008">constexpr</span><span style=3D"color:#000"> const_to_comparison_a=
nd_hash_value</span><span style=3D"color:#660">(</span><span style=3D"color=
:#008">const</span><span style=3D"color:#000"> _Myt</span><span style=3D"co=
lor:#660">&amp;&amp;</span><span style=3D"color:#000"> other</span><span st=
yle=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">:</span><span style=3D"color:#000"> _Mybase</span><span sty=
le=3D"color:#660">(</span><span style=3D"color:#000">other</span><span styl=
e=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"=
color:#660">{}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 _Myt</span><span style=3D"color:#660">&amp;</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#008">operator</span><span style=3D"c=
olor:#660">=3D(</span><span style=3D"color:#008">const</span><span style=3D=
"color:#000"> _Myt</span><span style=3D"color:#660">&amp;</span><span style=
=3D"color:#000"> other</span><span style=3D"color:#660">)</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"c=
olor:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </sp=
an><span style=3D"color:#008">this</span><span style=3D"color:#660">-&gt;</=
span><span style=3D"color:#000">_Mybase</span><span style=3D"color:#660">::=
</span><span style=3D"color:#008">operator</span><span style=3D"color:#660"=
>=3D((</span><span style=3D"color:#008">const</span><span style=3D"color:#0=
00"> _Mybase</span><span style=3D"color:#660">&amp;)</span><span style=3D"c=
olor:#000">other</span><span style=3D"color:#660">);</span><span style=3D"c=
olor:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660=
">}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</=
span><span style=3D"color:#660">&amp;</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#008">operator</span><span style=3D"color:#660">=
=3D(</span><span style=3D"color:#008">const</span><span style=3D"color:#000=
"> _Myt</span><span style=3D"color:#660">&amp;&amp;</span><span style=3D"co=
lor:#000"> other</span><span style=3D"color:#660">)</span><span style=3D"co=
lor:#000"> </span><span style=3D"color:#660">{</span><span style=3D"color:#=
000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><spa=
n style=3D"color:#008">this</span></div></code></div></div>...</blockquote>=
</div></div></blockquote>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; 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_169_198855859.1436968227037--
------=_Part_168_996300156.1436968227035--

.


Author: Omer Rosler <omer.rosler@gmail.com>
Date: Wed, 15 Jul 2015 08:49:50 -0700 (PDT)
Raw View
------=_Part_6781_612488971.1436975390291
Content-Type: multipart/alternative;
 boundary="----=_Part_6782_802750296.1436975390292"

------=_Part_6782_802750296.1436975390292
Content-Type: text/plain; charset=UTF-8

Of course I want to hash on the underlying type, but I don't want to create
another function to do it for me like in your example. In the original
suggstion the function simply called a hasher once (on the real object),
saved the value and returned it as if the object is const (this all done in
a single template and not comparator specific like in your example), but
this takes more momery (sizeof(size_t) per object).
I see the problem in using static hashers, maybe a few static functions
that can change the state of the hasher.
Well, if this limited-access class is not that common than this discussion
is pointless anyway...




On Wednesday, July 15, 2015 at 4:50:27 PM UTC+3, Edward Catmur wrote:
>
> On Wednesday, 15 July 2015 13:44:04 UTC+1, Omer Rosler wrote:
>>
>> First, Thanks for the feedback.
>> The reason I used the default value of the Comparator to be std::equal_to
>> is because I wanted this class to be a stand-alone, regardless of
>> containers; containers will use it with !comp(lhs, rhs) && !comp(rhs,
>> lhs) instead of this default value as you mentionted.
>> I did not know about the mutable keyword, this simplifies things alot, so
>> thank you for that.
>> About the unordered containers: I don't want to define a new hash
>> function every time I use an unordered container with this type, although I
>> can't see a solution that doesn't take more memory (or any possible way of
>> making a template hasher that performs a hash on a representative for
>> general type and general comparator).
>>
>
> Why not just use the hash on the underlying type?
>
>
>> If a limited access wrapper like this is a common nescessity (beyond
>> mutable keys in associative containers) then maybe it is worth standarizing
>> on it's own.
>> If so, the comparator needs not to come from a container, so using a
>> static member is probably the solution.
>>
>
> The problem there is that hashers can have state (e.g. a function pointer
> or a type-erased function wrapper), so a static member won't work. I can't
> think of any use other than associative containers, so you might as well
> use the container's comparator and hasher.
>
>
>> So, is this limited access wrapper worth standarizing?
>>
>> On Tuesday, July 14, 2015 at 11:23:45 PM UTC+3, Omer Rosler wrote:
>>>
>>> This is the first time I share my ideas about C++, so don't be too harsh
>>> :)
>>> This post is an attempt to partially solve the problem of key
>>> replacement  in (unordered) associative containers such as
>>> (unordered_)(multi)map, (unordered_)(multi)set* when the object doesn't
>>> move inside the container after replacement and the value *up to the
>>> comparator* is the same.
>>> *The braces () mean optiopnal.
>>> Note that in ordered containers if the value doesn't change (up to the
>>> comparator) so does the position of the object; in unordered this gets
>>> trickier, but we'll get to that later.
>>> My aproach is to create an intermediate class that provides a const-like
>>> access to a object but allows changing it if a comparator yields true (so
>>> the complexity of the assignment operator is the maximum of the complexity
>>> of the object type's assignemnt operator, and the comparator's complexity).
>>> In case of setting a diffrent value this class can either throw some
>>> exception or simply do nothing (up for debate).
>>> By using this class inside the underlying RB tree as the value type
>>> (instead of a simple const type) it will allow iterators to change the
>>> value of the key they hold by calling the wrapper class's assignemnt
>>> iterator.
>>> I haven't decided whether it's smart to make this class public and
>>> change the containers' value type (meaning: big diffrence from older
>>> versions for all 8 containers, although the conversion operator makes old
>>> code work all the same), or simply make it private and convert to
>>> container's value type inside the iterators which will now have setter
>>> functions.
>>> The second option has major downsides: The current iterators interface
>>> needs to be changed, instead of holding const key as a public member (like
>>> it does now), it will hold this wrapper class as a private/protected
>>> member, and accessing it must be done using a function call to a getter
>>> that calls a conversion operator (so access is using funtion calls only,
>>> instead of accessing a public member):
>>> template<class Key_type, Compare Comparator = std::equal_to<Key_type> >
>>> struct iterator {
>>>         //other code...
>>>         const Key_type& key() const { //getter
>>>                 return m_value; //call conversion operator
>>>         }
>>>         const Key_type& key(const Key_type&x) { //setter
>>>                 return m_value = x; //call copy assignment operator of
>>> wrapper class
>>>         }
>>> private:
>>>         const_to_comparison<Key_type, Comparator> m_value
>>> };
>>>
>>> (The name 'key' isn't the real function name, for map iterator it will
>>> be 'first', and for the set iterator it will be operator* for getter and
>>> set (maybe not a good name in this case) for setter)
>>> It is possible to be made compatible with other versions but will make
>>> the container to hold another public member for the converted type which
>>> takes twice the memory it used to.
>>> So maybe the first option where this wrapper class is public is better
>>> (at least in my opinion).
>>> Maybe there are other places this const-like access can be used.
>>> Well, the wrapper looks basically like this:
>>>
>>> namespace std {
>>> template<class _Kty, Compare _Pr = std::equal_to<_Kty> >
>>> class const_to_comparison {
>>>         typedef const_to_comparison<_Kty, _Pr> _Myt;
>>>         typedef _Kty key_type;
>>>         typedef _Pr key_compare;
>>>         static const key_compare comp = _Pr();
>>> public:
>>>         constexpr const_to_comparison() = default;
>>>         constexpr const_to_comparison(const key_type& key) : m_value(key
>>> ) {}
>>>         constexpr const_to_comparison(const _Myt& other) : m_value(other
>>> .key) {}
>>>         constexpr const_to_comparison(const _Myt&& other) : m_value(
>>> other.key) {}
>>>                 _Myt& operator=(const_to_comparison&& other) {
>>>                 if (!comp(m_value, other.m_value))
>>>                          std::bad_exception("can't change this value"); //colud
>>> be any other exception or simply do nothing
>>>                 m_value = other.m_value; //calling move operator=
>>>         }
>>>         _Myt& operator=(const_to_comparison& other) {
>>>                 if (!comp(m_value, other.m_value))
>>>                          std::bad_exception("can't change this value"); //colud
>>> be any other exception or simply do nothing
>>>                 m_value = other.m_value; //calling copy operator=
>>>         }
>>>         operator const _Kty&() { //for casting to the container's
>>> value_type inside the iterator
>>>                 return m_value;
>>>         }
>>>         ~const_to_comparison() = default;
>>> private:
>>>         key_type m_value;
>>> };
>>> }
>>>
>>> For unordered containers this obviously wouldn't work since the hash
>>> value would change every time the key changes and so will the position in
>>> the container, and this whole mechanism will fail.
>>> Therefore the hash value must remain constant after equal key
>>> replacement, so I tried to solve it the simplest way I could think of (I
>>> don't really like this solution so feel free to rip it to shreds):
>>> Save the hash value of the original object in another field and overload
>>> std::hash of this wrapper class to return this field.
>>> Something like this:
>>>
>>> namespace std {
>>> template<class _Kty, Compare _Pr = std::equal_to<_Kty>, Hash _Hasher =
>>> std::hash<_Kty> >
>>> class const_to_comparison_and_hash_value : public const_to_comparison <
>>> _Kty, _Pr > {
>>>         typedef const_to_comparison< _Kty, _Pr> _Mybase;
>>>         typedef const_to_comparison_and_hash_value<_Kty, _Pr, _Hasher>
>>> _Myt;
>>>         typedef _Kty key_type;
>>>         typedef _Pr key_compare;
>>>         typedef _Hasher key_hash;
>>>         static const key_hash hash = _Hasher();
>>> public:
>>>         constexpr const_to_comparison_and_hash_value() : _Mybase() {}
>>>         constexpr const_to_comparison_and_hash_value(const key_type&
>>> other) : _Mybase(other) {}
>>>         constexpr const_to_comparison_and_hash_value(const _Mybase&
>>> other) : _Mybase(other) {}
>>>         constexpr const_to_comparison_and_hash_value(const _Myt& other)
>>> : _Mybase(other) {}
>>>         constexpr const_to_comparison_and_hash_value(const _Myt&& other)
>>> : _Mybase(other) {}
>>>         _Myt& operator=(const _Myt& other) {
>>>                 this->_Mybase::operator=((const _Mybase&)other);
>>>         }
>>>         _Myt& operator=(const _Myt&& other) {
>>>                this
>>> ...
>>
>>

--

---
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_6782_802750296.1436975390292
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Of course I want to hash on the underlying type, but I don=
&#39;t want to create another function to do it for me like in your example=
.. In the original suggstion the function simply called a hasher once (on th=
e real object), saved the value and returned it as if the object is const (=
this all done in a single template and not comparator specific like in your=
 example), but this takes more momery (sizeof(size_t) per object).<div>I se=
e the problem in using static hashers, maybe a few static functions that ca=
n change the state of the hasher.</div><div>Well, if this limited-access cl=
ass is not that common than this discussion is pointless anyway...</div><di=
v><br><br><div><br><br>On Wednesday, July 15, 2015 at 4:50:27 PM UTC+3, Edw=
ard Catmur wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Wednesday,=
 15 July 2015 13:44:04 UTC+1, Omer Rosler  wrote:<blockquote class=3D"gmail=
_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padd=
ing-left:1ex"><div dir=3D"ltr">First, Thanks for the feedback.<div>The reas=
on I used the default value of the Comparator to be std::equal_to is becaus=
e I wanted this class to be a stand-alone, regardless of containers; contai=
ners will use it with=C2=A0<span style=3D"font-family:&#39;courier new&#39;=
,monospace">!comp(lhs, rhs) &amp;&amp; !comp(rhs, lhs)</span>=C2=A0instead =
of this default value as you mentionted.</div><div>I did not know about the=
 mutable keyword, this simplifies things alot, so thank you for that.</div>=
<div>About the unordered containers: I don&#39;t want to define a new hash =
function every time I use an unordered container with this type, although I=
 can&#39;t see a solution that doesn&#39;t take more memory (or any possibl=
e way of making a template hasher that performs a hash on a representative =
for general type and general comparator).</div></div></blockquote><div><br>=
</div><div>Why not just use the hash on the underlying type?</div><div>=C2=
=A0</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>If a=
 limited access wrapper like this is a common nescessity (beyond mutable ke=
ys in associative containers) then maybe it is worth standarizing on it&#39=
;s own.</div><div>If so, the comparator needs not to come from a container,=
 so using a static member is probably the solution.</div></div></blockquote=
><div><br></div><div>The problem there is that hashers can have state (e.g.=
 a function pointer or a type-erased function wrapper), so a static member =
won&#39;t work. I can&#39;t think of any use other than associative contain=
ers, so you might as well use the container&#39;s comparator and hasher.</d=
iv><div>=C2=A0</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=
"><div>So, is this limited access wrapper worth standarizing?<br><br>On Tue=
sday, July 14, 2015 at 11:23:45 PM UTC+3, Omer Rosler wrote:<blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc=
 solid;padding-left:1ex"><div dir=3D"ltr"><div>This is the first time I sha=
re my ideas about C++, so don&#39;t be too harsh :)<br></div><div>This post=
 is an attempt to partially solve the problem of key replacement =C2=A0in (=
unordered) associative containers such as</div><div>(unordered_)(multi)map,=
 (unordered_)(multi)set* when the object doesn&#39;t move inside the contai=
ner after replacement and the value <b>up to the comparator</b> is the same=
..</div><div>*The braces () mean optiopnal.</div><div>Note that in ordered c=
ontainers if the value doesn&#39;t change (up to the comparator) so does th=
e position of the object; in unordered this gets trickier, but we&#39;ll ge=
t to that later.</div><div>My aproach is to create an intermediate class th=
at provides a const-like access to a object but allows changing it if a com=
parator yields true (so the complexity of the assignment operator is the ma=
ximum of the complexity of the object type&#39;s assignemnt operator, and t=
he comparator&#39;s complexity).</div><div>In case of setting a diffrent va=
lue this class can either throw some exception or simply do nothing (up for=
 debate).</div><div>By using this class inside the underlying RB tree as th=
e value type (instead of a simple const type) it will allow iterators to ch=
ange the value of the key they hold by calling the wrapper class&#39;s assi=
gnemnt iterator.</div><div>I haven&#39;t decided whether it&#39;s smart to =
make this class public and change the containers&#39; value type (meaning: =
big diffrence from older versions for all 8 containers, although the conver=
sion operator makes old code work all the same), or simply make it private =
and convert to container&#39;s value type inside the iterators which will n=
ow have setter functions.</div><div>The second option has major downsides: =
The current iterators interface needs to be changed, instead of holding con=
st key as a public member (like it does now), it will hold this wrapper cla=
ss as a private/protected member, and accessing it must be done using a fun=
ction call to a getter that calls a conversion operator (so access is using=
 funtion calls only, instead of accessing a public member):</div><div><div =
style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;background-=
color:rgb(250,250,250)"><code><div><span style=3D"color:#008">template</spa=
n><span style=3D"color:#660">&lt;</span><span style=3D"color:#008">class</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#606">Key_type<=
/span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </span=
><span style=3D"color:#606">Compare</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#606">Comparator</span><span style=3D"color:#000"> <=
/span><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> std<=
/span><span style=3D"color:#660">::</span><span style=3D"color:#000">equal_=
to</span><span style=3D"color:#660">&lt;</span><span style=3D"color:#606">K=
ey_type</span><span style=3D"color:#660">&gt;</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#660">&gt;</span><span style=3D"color:#000=
"><br></span><span style=3D"color:#008">struct</span><span style=3D"color:#=
000"> iterator </span><span style=3D"color:#660">{</span><span style=3D"col=
or:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#800">=
//other code...</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color:#008">const</span><span style=3D"color:#=
000"> </span><span style=3D"color:#606">Key_type</span><span style=3D"color=
:#660">&amp;</span><span style=3D"color:#000"> key</span><span style=3D"col=
or:#660">()</span><span style=3D"color:#000"> </span><span style=3D"color:#=
008">const</span><font color=3D"#666600"><span style=3D"color:#000"> </span=
><span style=3D"color:#660">{</span></font><span style=3D"color:#000"> </sp=
an><span style=3D"color:#800">//getter</span><span style=3D"color:#000"><br=
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=
=3D"color:#008">return</span><span style=3D"color:#000"> m_value</span><spa=
n style=3D"color:#660">;</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#800">//</span><font color=3D"#000000"><span style=3D"color:#80=
0">call conversion operator</span><span style=3D"color:#000"><br></span></f=
ont><span style=3D"color:#000">=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span sty=
le=3D"color:#660">}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 </span><span style=3D"color:#008">const</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#606">Key_type</span><span style=3D"c=
olor:#660">&amp;</span><span style=3D"color:#000"> key</span><span style=3D=
"color:#660">(</span><span style=3D"color:#008">const</span><span style=3D"=
color:#000"> </span><span style=3D"color:#606">Key_type</span><span style=
=3D"color:#660">&amp;</span><span style=3D"color:#000">x</span><span style=
=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#660">{</span><span style=3D"color:#000"> </span><span style=3D"color:=
#800">//setter</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return=
</span><span style=3D"color:#000"> m_value </span><span style=3D"color:#660=
">=3D</span><span style=3D"color:#000"> x</span><span style=3D"color:#660">=
;</span><span style=3D"color:#000"> </span><span style=3D"color:#800">//cal=
l copy assignment operator of wrapper class</span><span style=3D"color:#000=
"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span=
><span style=3D"color:#000"><br></span><span style=3D"color:#008">private</=
span><span style=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 const_to_comparison</span><span style=3D"color:#66=
0">&lt;</span><span style=3D"color:#606">Key_type</span><span style=3D"colo=
r:#660">,</span><span style=3D"color:#000"> </span><span style=3D"color:#60=
6">Comparator</span><span style=3D"color:#660">&gt;</span><span style=3D"co=
lor:#000"> m_value<br></span><span style=3D"color:#660">};</span><font colo=
r=3D"#666600"></font></div></code></div></div><div><br></div><div>(The name=
 &#39;key&#39; isn&#39;t the real function name, for map iterator it will b=
e &#39;first&#39;, and for the set iterator it will be operator* for getter=
 and set (maybe not a good name in this case) for setter)</div><div>It is p=
ossible to be made compatible with other versions but will make the contain=
er to hold another public member for the converted type which takes twice t=
he memory it used to.</div><div>So maybe the first option where this wrappe=
r class is public is better (at least in my opinion).</div><div>Maybe there=
 are other places this const-like access can be used.</div><div>Well, the w=
rapper looks basically like this:</div><div><br></div><div style=3D"border:=
1px solid rgb(187,187,187);word-wrap:break-word;background-color:rgb(250,25=
0,250)"><code><div><span style=3D"color:#008">namespace</span><span style=
=3D"color:#000"> std </span><span style=3D"color:#660">{</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#008">template</span><span =
style=3D"color:#660">&lt;</span><span style=3D"color:#008">class</span><spa=
n style=3D"color:#000"> _Kty</span><span style=3D"color:#660">,</span><span=
 style=3D"color:#000"> </span><span style=3D"color:#606">Compare</span><spa=
n style=3D"color:#000"> _Pr </span><span style=3D"color:#660">=3D</span><sp=
an style=3D"color:#000"> std</span><span style=3D"color:#660">::</span><spa=
n style=3D"color:#000">equal_to</span><span style=3D"color:#660">&lt;</span=
><span style=3D"color:#000">_Kty</span><span style=3D"color:#660">&gt;</spa=
n><span style=3D"color:#000"> </span><span style=3D"color:#660">&gt;</span>=
<span style=3D"color:#000"><br></span><span style=3D"color:#008">class</spa=
n><span style=3D"color:#000"> const_to_comparison </span><span style=3D"col=
or:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0=
 </span><span style=3D"color:#008">typedef</span><span style=3D"color:#000"=
> const_to_comparison</span><span style=3D"color:#660">&lt;</span><span sty=
le=3D"color:#000">_Kty</span><span style=3D"color:#660">,</span><span style=
=3D"color:#000"> _Pr</span><span style=3D"color:#660">&gt;</span><span styl=
e=3D"color:#000"> _Myt</span><span style=3D"color:#660">;</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color=
:#008">typedef</span><span style=3D"color:#000"> _Kty key_type</span><span =
style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 </span><span style=3D"color:#008">typedef</span><span style=
=3D"color:#000"> _Pr key_compare</span><span style=3D"color:#660">;</span><=
span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span styl=
e=3D"color:#008">static</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#008">const</span><span style=3D"color:#000"> key_compare comp <=
/span><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> _Pr<=
/span><span style=3D"color:#660">();</span><span style=3D"color:#000"><br><=
/span><span style=3D"color:#008">public</span><span style=3D"color:#660">:<=
/span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><sp=
an style=3D"color:#008">constexpr</span><span style=3D"color:#000"> const_t=
o_comparison</span><span style=3D"color:#660">()</span><span style=3D"color=
:#000"> </span><span style=3D"color:#660">=3D</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#008">default</span><span style=3D"color:#=
660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </s=
pan><span style=3D"color:#008">constexpr</span><span style=3D"color:#000"> =
const_to_comparison</span><span style=3D"color:#660">(</span><span style=3D=
"color:#008">const</span><span style=3D"color:#000"> key_type</span><span s=
tyle=3D"color:#660">&amp;</span><span style=3D"color:#000"> key</span><span=
 style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#660">:</span><span style=3D"color:#000"> m_value</span><span st=
yle=3D"color:#660">(</span><span style=3D"color:#000">key</span><span style=
=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#660">{}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 </span><span style=3D"color:#008">constexpr</span><span style=3D"color:=
#000"> const_to_comparison</span><span style=3D"color:#660">(</span><span s=
tyle=3D"color:#008">const</span><span style=3D"color:#000"> _Myt</span><spa=
n style=3D"color:#660">&amp;</span><span style=3D"color:#000"> other</span>=
<span style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span=
 style=3D"color:#660">:</span><span style=3D"color:#000"> m_value</span><sp=
an style=3D"color:#660">(</span><span style=3D"color:#000">other</span><spa=
n style=3D"color:#660">.</span><span style=3D"color:#000">key</span><span s=
tyle=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">{}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</span><span style=3D=
"color:#000"> const_to_comparison</span><span style=3D"color:#660">(</span>=
<span style=3D"color:#008">const</span><span style=3D"color:#000"> _Myt</sp=
an><span style=3D"color:#660">&amp;&amp;</span><span style=3D"color:#000"> =
other</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> =
</span><span style=3D"color:#660">:</span><span style=3D"color:#000"> m_val=
ue</span><span style=3D"color:#660">(</span><span style=3D"color:#000">othe=
r</span><span style=3D"color:#660">.</span><span style=3D"color:#000">key</=
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>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</span><span style=3D"=
color:#660">&amp;</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#008">operator</span><span style=3D"color:#660">=3D(</span><span style=
=3D"color:#000">const_to_comparison</span><span style=3D"color:#660">&amp;&=
amp;</span><span style=3D"color:#000"> other</span><span style=3D"color:#66=
0">)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{<=
/span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">if</span><span style=3D=
"color:#000"> </span><span style=3D"color:#660">(!</span><span style=3D"col=
or:#000">comp</span><span style=3D"color:#660">(</span><span style=3D"color=
:#000">m_value</span><span style=3D"color:#660">,</span><span style=3D"colo=
r:#000"> other</span><span style=3D"color:#660">.</span><span style=3D"colo=
r:#000">m_value</span><span style=3D"color:#660">))</span><span style=3D"co=
lor:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0std</span><span style=3D"color:#660">::</spa=
n><span style=3D"color:#000">bad_exception</span><span style=3D"color:#660"=
>(</span><span style=3D"color:#080">&quot;can&#39;t change this value&quot;=
</span><span style=3D"color:#660">);</span><span style=3D"color:#000"> </sp=
an><span style=3D"color:#800">//colud be any other exception or simply do n=
othing</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 m_value </span><span style=3D"color:#660">=3D</spa=
n><span style=3D"color:#000"> other</span><span style=3D"color:#660">.</spa=
n><span style=3D"color:#000">m_value</span><span style=3D"color:#660">;</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#800">//calling =
move operator=3D</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color:#660">}</span><span style=3D"color:#000"=
><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</span><span style=3D"color:#660">&amp=
;</span><span style=3D"color:#000"> </span><span style=3D"color:#008">opera=
tor</span><span style=3D"color:#660">=3D(</span><span style=3D"color:#000">=
const_to_comparison</span><span style=3D"color:#660">&amp;</span><span styl=
e=3D"color:#000"> other</span><span style=3D"color:#660">)</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"=
color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </s=
pan><span style=3D"color:#008">if</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#660">(!</span><span style=3D"color:#000">comp</span><=
span style=3D"color:#660">(</span><span style=3D"color:#000">m_value</span>=
<span style=3D"color:#660">,</span><span style=3D"color:#000"> other</span>=
<span style=3D"color:#660">.</span><span style=3D"color:#000">m_value</span=
><span style=3D"color:#660">))</span><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0std</span><span style=3D"color:#660">::</span><span style=3D"colo=
r:#000">bad_exception</span><span style=3D"color:#660">(</span><span style=
=3D"color:#080">&quot;can&#39;t change this value&quot;</span><span style=
=3D"color:#660">);</span><span style=3D"color:#000"> </span><span style=3D"=
color:#800">//colud be any other exception or simply do nothing</span><span=
 style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 m_value </span><span style=3D"color:#660">=3D</span><span style=3D"c=
olor:#000"> other</span><span style=3D"color:#660">.</span><span style=3D"c=
olor:#000">m_value</span><span style=3D"color:#660">;</span><span style=3D"=
color:#000"> </span><span style=3D"color:#800">//calling copy operator=3D</=
span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><spa=
n style=3D"color:#660">}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0=
 =C2=A0 =C2=A0 </span><span style=3D"color:#008">operator</span><span style=
=3D"color:#000"> </span><span style=3D"color:#008">const</span><span style=
=3D"color:#000"> _Kty</span><span style=3D"color:#660">&amp;()</span><span =
style=3D"color:#000"> </span><span style=3D"color:#660">{</span><span style=
=3D"color:#000"> </span><span style=3D"color:#800">//for casting to the con=
tainer&#39;s value_type inside the iterator</span><span style=3D"color:#000=
"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span =
style=3D"color:#008">return</span><span style=3D"color:#000"> m_value</span=
><span style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color=
:#660">~</span><span style=3D"color:#000">const_to_comparison</span><span s=
tyle=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:#008">default</span><span style=3D"color:#660">;</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#008">private</span><span s=
tyle=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 key_type m_value</span><span style=3D"color:#660">;</span><sp=
an style=3D"color:#000"><br></span><span style=3D"color:#660">};</span><spa=
n style=3D"color:#000"><br></span><span style=3D"color:#660">}</span></div>=
</code></div><div style=3D"font-family:monospace;background-color:rgb(250,2=
50,250)"><br></div><div>For unordered containers this obviously wouldn&#39;=
t work since the hash value would change every time the key changes and so =
will the position in the container, and this whole mechanism will fail.</di=
v><div>Therefore the hash value must remain constant after equal key replac=
ement, so I tried to solve it the simplest way I could think of (I don&#39;=
t really like this solution so feel free to rip it to shreds):</div><div>Sa=
ve the hash value of the original object in another field and overload std:=
:hash of this wrapper class to return this field.</div><div>Something like =
this:</div><div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-=
word;background-color:rgb(250,250,250)"><code><div><span style=3D"color:#00=
0"><br></span><span style=3D"color:#008">namespace</span><span style=3D"col=
or:#000"> std </span><span style=3D"color:#660">{</span><span style=3D"colo=
r:#000"><br></span><span style=3D"color:#008">template</span><span style=3D=
"color:#660">&lt;</span><span style=3D"color:#008">class</span><span style=
=3D"color:#000"> _Kty</span><span style=3D"color:#660">,</span><span style=
=3D"color:#000"> </span><span style=3D"color:#606">Compare</span><span styl=
e=3D"color:#000"> _Pr </span><span style=3D"color:#660">=3D</span><span sty=
le=3D"color:#000"> std</span><span style=3D"color:#660">::</span><span styl=
e=3D"color:#000">equal_to</span><span style=3D"color:#660">&lt;</span><span=
 style=3D"color:#000">_Kty</span><span style=3D"color:#660">&gt;,</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#606">Hash</span><span=
 style=3D"color:#000"> _Hasher </span><span style=3D"color:#660">=3D</span>=
<span style=3D"color:#000"> std</span><span style=3D"color:#660">::</span><=
span style=3D"color:#000">hash</span><span style=3D"color:#660">&lt;</span>=
<span style=3D"color:#000">_Kty</span><span style=3D"color:#660">&gt;</span=
><span style=3D"color:#000"> </span><span style=3D"color:#660">&gt;</span><=
span style=3D"color:#000"><br></span><span style=3D"color:#008">class</span=
><span style=3D"color:#000"> const_to_comparison_and_hash_value </span><spa=
n style=3D"color:#660">:</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#008">public</span><span style=3D"color:#000"> const_to_compari=
son </span><span style=3D"color:#660">&lt;</span><span style=3D"color:#000"=
> _Kty</span><span style=3D"color:#660">,</span><span style=3D"color:#000">=
 _Pr </span><span style=3D"color:#660">&gt;</span><span style=3D"color:#000=
"> </span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br=
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typedef</spa=
n><span style=3D"color:#000"> const_to_comparison</span><span style=3D"colo=
r:#660">&lt;</span><span style=3D"color:#000"> _Kty</span><span style=3D"co=
lor:#660">,</span><span style=3D"color:#000"> _Pr</span><span style=3D"colo=
r:#660">&gt;</span><span style=3D"color:#000"> _Mybase</span><span style=3D=
"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color:#008">typedef</span><span style=3D"color=
:#000"> const_to_comparison_and_hash_value</span><span style=3D"color:#660"=
>&lt;</span><span style=3D"color:#000">_Kty</span><span style=3D"color:#660=
">,</span><span style=3D"color:#000"> _Pr</span><span style=3D"color:#660">=
,</span><span style=3D"color:#000"> _Hasher</span><span style=3D"color:#660=
">&gt;</span><span style=3D"color:#000"> _Myt</span><span style=3D"color:#6=
60">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </sp=
an><span style=3D"color:#008">typedef</span><span style=3D"color:#000"> _Kt=
y key_type</span><span style=3D"color:#660">;</span><span style=3D"color:#0=
00"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typed=
ef</span><span style=3D"color:#000"> _Pr key_compare</span><span style=3D"c=
olor:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 </span><span style=3D"color:#008">typedef</span><span style=3D"color:#0=
00"> _Hasher key_hash</span><span style=3D"color:#660">;</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color=
:#008">static</span><span style=3D"color:#000"> </span><span style=3D"color=
:#008">const</span><span style=3D"color:#000"> key_hash hash </span><span s=
tyle=3D"color:#660">=3D</span><span style=3D"color:#000"> _Hasher</span><sp=
an style=3D"color:#660">();</span><span style=3D"color:#000"><br></span><sp=
an style=3D"color:#008">public</span><span style=3D"color:#660">:</span><sp=
an style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=
=3D"color:#008">constexpr</span><span style=3D"color:#000"> const_to_compar=
ison_and_hash_value</span><span style=3D"color:#660">()</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">:</span><span style=3D"c=
olor:#000"> _Mybase</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>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#00=
8">constexpr</span><span style=3D"color:#000"> const_to_comparison_and_hash=
_value</span><span style=3D"color:#660">(</span><span style=3D"color:#008">=
const</span><span style=3D"color:#000"> key_type</span><span style=3D"color=
:#660">&amp;</span><span style=3D"color:#000"> other</span><span style=3D"c=
olor:#660">)</span><span style=3D"color:#000"> </span><span style=3D"color:=
#660">:</span><span style=3D"color:#000"> _Mybase</span><span style=3D"colo=
r:#660">(</span><span style=3D"color:#000">other</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>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </spa=
n><span style=3D"color:#008">constexpr</span><span style=3D"color:#000"> co=
nst_to_comparison_and_hash_value</span><span style=3D"color:#660">(</span><=
span style=3D"color:#008">const</span><span style=3D"color:#000"> _Mybase</=
span><span style=3D"color:#660">&amp;</span><span style=3D"color:#000"> oth=
er</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#660">:</span><span style=3D"color:#000"> _Mybase<=
/span><span style=3D"color:#660">(</span><span style=3D"color:#000">other</=
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>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</span><spa=
n style=3D"color:#000"> const_to_comparison_and_hash_value</span><span styl=
e=3D"color:#660">(</span><span style=3D"color:#008">const</span><span style=
=3D"color:#000"> _Myt</span><span style=3D"color:#660">&amp;</span><span st=
yle=3D"color:#000"> other</span><span style=3D"color:#660">)</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#660">:</span><span style=
=3D"color:#000"> _Mybase</span><span style=3D"color:#660">(</span><span sty=
le=3D"color:#000">other</span><span style=3D"color:#660">)</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#660">{}</span><span style=3D=
"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#0=
08">constexpr</span><span style=3D"color:#000"> const_to_comparison_and_has=
h_value</span><span style=3D"color:#660">(</span><span style=3D"color:#008"=
>const</span><span style=3D"color:#000"> _Myt</span><span style=3D"color:#6=
60">&amp;&amp;</span><span style=3D"color:#000"> other</span><span style=3D=
"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"colo=
r:#660">:</span><span style=3D"color:#000"> _Mybase</span><span style=3D"co=
lor:#660">(</span><span style=3D"color:#000">other</span><span style=3D"col=
or:#660">)</span><span style=3D"color:#000"> </span><span style=3D"color:#6=
60">{}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 _My=
t</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#000"> =
</span><span style=3D"color:#008">operator</span><span style=3D"color:#660"=
>=3D(</span><span style=3D"color:#008">const</span><span style=3D"color:#00=
0"> _Myt</span><span style=3D"color:#660">&amp;</span><span style=3D"color:=
#000"> other</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>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span s=
tyle=3D"color:#008">this</span><span style=3D"color:#660">-&gt;</span><span=
 style=3D"color:#000">_Mybase</span><span style=3D"color:#660">::</span><sp=
an style=3D"color:#008">operator</span><span style=3D"color:#660">=3D((</sp=
an><span style=3D"color:#008">const</span><span style=3D"color:#000"> _Myba=
se</span><span style=3D"color:#660">&amp;)</span><span style=3D"color:#000"=
>other</span><span style=3D"color:#660">);</span><span style=3D"color:#000"=
><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span>=
<span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</span><span=
 style=3D"color:#660">&amp;</span><span style=3D"color:#000"> </span><span =
style=3D"color:#008">operator</span><span style=3D"color:#660">=3D(</span><=
span style=3D"color:#008">const</span><span style=3D"color:#000"> _Myt</spa=
n><span style=3D"color:#660">&amp;&amp;</span><span style=3D"color:#000"> o=
ther</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>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"c=
olor:#008">this</span></div></code></div></div>...</blockquote></div></div>=
</blockquote></blockquote></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&quot; 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_6782_802750296.1436975390292--
------=_Part_6781_612488971.1436975390291--

.


Author: Edward Catmur <ed@catmur.co.uk>
Date: Wed, 15 Jul 2015 08:59:02 -0700 (PDT)
Raw View
------=_Part_6665_2086303566.1436975942164
Content-Type: multipart/alternative;
 boundary="----=_Part_6666_1771605933.1436975942165"

------=_Part_6666_1771605933.1436975942165
Content-Type: text/plain; charset=UTF-8

In the cases where it's legitimate to modify the key (generally a record
where only some fields participate in the key identity) one has to provide
a hasher and comparator expressing that restricted identity concept; that's
what my example was intended to model. There's no need to provide another
hasher or comparator.

Perhaps I misunderstood your intent; could you provide a simple use case
like I did above?

On Wednesday, 15 July 2015 16:49:50 UTC+1, Omer Rosler wrote:
>
> Of course I want to hash on the underlying type, but I don't want to
> create another function to do it for me like in your example. In the
> original suggstion the function simply called a hasher once (on the real
> object), saved the value and returned it as if the object is const (this
> all done in a single template and not comparator specific like in your
> example), but this takes more momery (sizeof(size_t) per object).
> I see the problem in using static hashers, maybe a few static functions
> that can change the state of the hasher.
> Well, if this limited-access class is not that common than this discussion
> is pointless anyway...
>
> On Wednesday, July 15, 2015 at 4:50:27 PM UTC+3, Edward Catmur wrote:
>>
>> On Wednesday, 15 July 2015 13:44:04 UTC+1, Omer Rosler wrote:
>>>
>>> First, Thanks for the feedback.
>>> The reason I used the default value of the Comparator to be
>>> std::equal_to is because I wanted this class to be a stand-alone,
>>> regardless of containers; containers will use it with !comp(lhs, rhs)
>>> && !comp(rhs, lhs) instead of this default value as you mentionted.
>>> I did not know about the mutable keyword, this simplifies things alot,
>>> so thank you for that.
>>> About the unordered containers: I don't want to define a new hash
>>> function every time I use an unordered container with this type, although I
>>> can't see a solution that doesn't take more memory (or any possible way of
>>> making a template hasher that performs a hash on a representative for
>>> general type and general comparator).
>>>
>>
>> Why not just use the hash on the underlying type?
>>
>>
>>> If a limited access wrapper like this is a common nescessity (beyond
>>> mutable keys in associative containers) then maybe it is worth standarizing
>>> on it's own.
>>> If so, the comparator needs not to come from a container, so using a
>>> static member is probably the solution.
>>>
>>
>> The problem there is that hashers can have state (e.g. a function pointer
>> or a type-erased function wrapper), so a static member won't work. I can't
>> think of any use other than associative containers, so you might as well
>> use the container's comparator and hasher.
>>
>>
>>> So, is this limited access wrapper worth standarizing?
>>>
>>> On Tuesday, July 14, 2015 at 11:23:45 PM UTC+3, Omer Rosler wrote:
>>>>
>>>> This is the first time I share my ideas about C++, so don't be too
>>>> harsh :)
>>>> This post is an attempt to partially solve the problem of key
>>>> replacement  in (unordered) associative containers such as
>>>> (unordered_)(multi)map, (unordered_)(multi)set* when the object doesn't
>>>> move inside the container after replacement and the value *up to the
>>>> comparator* is the same.
>>>> *The braces () mean optiopnal.
>>>> Note that in ordered containers if the value doesn't change (up to the
>>>> comparator) so does the position of the object; in unordered this gets
>>>> trickier, but we'll get to that later.
>>>> My aproach is to create an intermediate class that provides a
>>>> const-like access to a object but allows changing it if a comparator yields
>>>> true (so the complexity of the assignment operator is the maximum of the
>>>> complexity of the object type's assignemnt operator, and the comparator's
>>>> complexity).
>>>> In case of setting a diffrent value this class can either throw some
>>>> exception or simply do nothing (up for debate).
>>>> By using this class inside the underlying RB tree as the value type
>>>> (instead of a simple const type) it will allow iterators to change the
>>>> value of the key they hold by calling the wrapper class's assignemnt
>>>> iterator.
>>>> I haven't decided whether it's smart to make this class public and
>>>> change the containers' value type (meaning: big diffrence from older
>>>> versions for all 8 containers, although the conversion operator makes old
>>>> code work all the same), or simply make it private and convert to
>>>> container's value type inside the iterators which will now have setter
>>>> functions.
>>>> The second option has major downsides: The current iterators interface
>>>> needs to be changed, instead of holding const key as a public member (like
>>>> it does now), it will hold this wrapper class as a private/protected
>>>> member, and accessing it must be done using a function call to a getter
>>>> that calls a conversion operator (so access is using funtion calls only,
>>>> instead of accessing a public member):
>>>> template<class Key_type, Compare Comparator = std::equal_to<Key_type> >
>>>> struct iterator {
>>>>         //other code...
>>>>         const Key_type& key() const { //getter
>>>>                 return m_value; //call conversion operator
>>>>         }
>>>>         const Key_type& key(const Key_type&x) { //setter
>>>>                 return m_value = x; //call copy assignment operator of
>>>> wrapper class
>>>>         }
>>>> private:
>>>>         const_to_comparison<Key_type, Comparator> m_value
>>>> };
>>>>
>>>> (The name 'key' isn't the real function name, for map iterator it will
>>>> be 'first', and for the set iterator it will be operator* for getter and
>>>> set (maybe not a good name in this case) for setter)
>>>> It is possible to be made compatible with other versions but will make
>>>> the container to hold another public member for the converted type which
>>>> takes twice the memory it used to.
>>>> So maybe the first option where this wrapper class is public is better
>>>> (at least in my opinion).
>>>> Maybe there are other places this const-like access can be used.
>>>> Well, the wrapper looks basically like this:
>>>>
>>>> namespace std {
>>>> template<class _Kty, Compare _Pr = std::equal_to<_Kty> >
>>>> class const_to_comparison {
>>>>         typedef const_to_comparison<_Kty, _Pr> _Myt;
>>>>         typedef _Kty key_type;
>>>>         typedef _Pr key_compare;
>>>>         static const key_compare comp = _Pr();
>>>> public:
>>>>         constexpr const_to_comparison() = default;
>>>>         constexpr const_to_comparison(const key_type& key) : m_value(
>>>> key) {}
>>>>         constexpr const_to_comparison(const _Myt& other) : m_value(
>>>> other.key) {}
>>>>         constexpr const_to_comparison(const _Myt&& other) : m_value(
>>>> other.key) {}
>>>>                 _Myt& operator=(const_to_comparison&& other) {
>>>>                 if (!comp(m_value, other.m_value))
>>>>                          std::bad_exception("can't change this value"); //colud
>>>> be any other exception or simply do nothing
>>>>                 m_value = other.m_value; //calling move operator=
>>>>         }
>>>>         _Myt& operator=(const_to_comparison& other) {
>>>>                 if (!comp(m_value, other.m_value))
>>>>                          std::bad_exception("can't change this value"); //colud
>>>> be any other exception or simply do nothing
>>>>                 m_value = other.m_value; //calling copy operator=
>>>>         }
>>>>         operator const _Kty&() { //for casting to the container's
>>>> value_type inside the iterator
>>>>                 return m_value;
>>>>         }
>>>>         ~const_to_comparison() = default;
>>>> private:
>>>>         key_type m_value;
>>>> };
>>>> }
>>>>
>>>> For unordered containers this obviously wouldn't work since the hash
>>>> value would change every time the key changes and so will the position in
>>>> the container, and this whole mechanism will fail.
>>>> Therefore the hash value must remain constant after equal key
>>>> replacement, so I tried to solve it the simplest way I could think of (I
>>>> don't really like this solution so feel free to rip it to shreds):
>>>> Save the hash value of the original object in another field and
>>>> overload std::hash of this wrapper class to return this field.
>>>> Something like this:
>>>>
>>>> namespace std {
>>>> template<class _Kty, Compare _Pr = std::equal_to<_Kty>, Hash _Hasher =
>>>> std::hash<_Kty> >
>>>> class const_to_comparison_and_hash_value : public const_to_comparison <
>>>> _Kty, _Pr > {
>>>>         typedef const_to_comparison< _Kty, _Pr> _Mybase;
>>>>         typedef const_to_comparison_and_hash_value<_Kty, _Pr, _Hasher>
>>>> _Myt;
>>>>         typedef _Kty key_type;
>>>>         typedef _Pr key_compare;
>>>>         typedef _Hasher key_hash;
>>>>         static const key_hash hash = _Hasher();
>>>> public:
>>>>         constexpr const_to_comparison_and_hash_value() : _Mybase() {}
>>>>         constexpr const_to_comparison_and_hash_value(const key_type&
>>>> other) : _Mybase(other) {}
>>>>         constexpr const_to_comparison_and_hash_value(const _Mybase&
>>>> other) : _Mybase(other) {}
>>>>         constexpr const_to_comparison_and_hash_value(const _Myt& other)
>>>> : _Mybase(other) {}
>>>>         constexpr const_to_comparison_and_hash_value(const _Myt&& other
>>>> ) : _Mybase(other) {}
>>>>         _Myt& operator=(const _Myt& other) {
>>>>                 this->_Mybase::operator=((const _Mybase&)other);
>>>>         }
>>>>         _Myt& operator=(const _Myt&& other) {
>>>>                this
>>>> ...
>>>
>>>

--

---
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_6666_1771605933.1436975942165
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">In the cases where it&#39;s legitimate to modify the key (=
generally a record where only some fields participate in the key identity) =
one has to provide a hasher and comparator expressing that restricted ident=
ity concept; that&#39;s what my example was intended to model. There&#39;s =
no need to provide another hasher or comparator.<div><br></div><div>Perhaps=
 I misunderstood your intent; could you provide a simple use case like I di=
d above?<br><br>On Wednesday, 15 July 2015 16:49:50 UTC+1, Omer Rosler  wro=
te:<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">Of course =
I want to hash on the underlying type, but I don&#39;t want to create anoth=
er function to do it for me like in your example. In the original suggstion=
 the function simply called a hasher once (on the real object), saved the v=
alue and returned it as if the object is const (this all done in a single t=
emplate and not comparator specific like in your example), but this takes m=
ore momery (sizeof(size_t) per object).<div>I see the problem in using stat=
ic hashers, maybe a few static functions that can change the state of the h=
asher.</div><div>Well, if this limited-access class is not that common than=
 this discussion is pointless anyway...</div><div><br><div>On Wednesday, Ju=
ly 15, 2015 at 4:50:27 PM UTC+3, Edward Catmur wrote:<blockquote class=3D"g=
mail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;=
padding-left:1ex">On Wednesday, 15 July 2015 13:44:04 UTC+1, Omer Rosler  w=
rote:<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">First, Thanks=
 for the feedback.<div>The reason I used the default value of the Comparato=
r to be std::equal_to is because I wanted this class to be a stand-alone, r=
egardless of containers; containers will use it with=C2=A0<span style=3D"fo=
nt-family:&#39;courier new&#39;,monospace">!comp(lhs, rhs) &amp;&amp; !comp=
(rhs, lhs)</span>=C2=A0instead of this default value as you mentionted.</di=
v><div>I did not know about the mutable keyword, this simplifies things alo=
t, so thank you for that.</div><div>About the unordered containers: I don&#=
39;t want to define a new hash function every time I use an unordered conta=
iner with this type, although I can&#39;t see a solution that doesn&#39;t t=
ake more memory (or any possible way of making a template hasher that perfo=
rms a hash on a representative for general type and general comparator).</d=
iv></div></blockquote><div><br></div><div>Why not just use the hash on the =
underlying type?</div><div>=C2=A0</div><blockquote class=3D"gmail_quote" st=
yle=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1=
ex"><div dir=3D"ltr"><div>If a limited access wrapper like this is a common=
 nescessity (beyond mutable keys in associative containers) then maybe it i=
s worth standarizing on it&#39;s own.</div><div>If so, the comparator needs=
 not to come from a container, so using a static member is probably the sol=
ution.</div></div></blockquote><div><br></div><div>The problem there is tha=
t hashers can have state (e.g. a function pointer or a type-erased function=
 wrapper), so a static member won&#39;t work. I can&#39;t think of any use =
other than associative containers, so you might as well use the container&#=
39;s comparator and hasher.</div><div>=C2=A0</div><blockquote class=3D"gmai=
l_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pad=
ding-left:1ex"><div dir=3D"ltr"><div>So, is this limited access wrapper wor=
th standarizing?<br><br>On Tuesday, July 14, 2015 at 11:23:45 PM UTC+3, Ome=
r Rosler 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"><di=
v>This is the first time I share my ideas about C++, so don&#39;t be too ha=
rsh :)<br></div><div>This post is an attempt to partially solve the problem=
 of key replacement =C2=A0in (unordered) associative containers such as</di=
v><div>(unordered_)(multi)map, (unordered_)(multi)set* when the object does=
n&#39;t move inside the container after replacement and the value <b>up to =
the comparator</b> is the same.</div><div>*The braces () mean optiopnal.</d=
iv><div>Note that in ordered containers if the value doesn&#39;t change (up=
 to the comparator) so does the position of the object; in unordered this g=
ets trickier, but we&#39;ll get to that later.</div><div>My aproach is to c=
reate an intermediate class that provides a const-like access to a object b=
ut allows changing it if a comparator yields true (so the complexity of the=
 assignment operator is the maximum of the complexity of the object type&#3=
9;s assignemnt operator, and the comparator&#39;s complexity).</div><div>In=
 case of setting a diffrent value this class can either throw some exceptio=
n or simply do nothing (up for debate).</div><div>By using this class insid=
e the underlying RB tree as the value type (instead of a simple const type)=
 it will allow iterators to change the value of the key they hold by callin=
g the wrapper class&#39;s assignemnt iterator.</div><div>I haven&#39;t deci=
ded whether it&#39;s smart to make this class public and change the contain=
ers&#39; value type (meaning: big diffrence from older versions for all 8 c=
ontainers, although the conversion operator makes old code work all the sam=
e), or simply make it private and convert to container&#39;s value type ins=
ide the iterators which will now have setter functions.</div><div>The secon=
d option has major downsides: The current iterators interface needs to be c=
hanged, instead of holding const key as a public member (like it does now),=
 it will hold this wrapper class as a private/protected member, and accessi=
ng it must be done using a function call to a getter that calls a conversio=
n operator (so access is using funtion calls only, instead of accessing a p=
ublic member):</div><div><div style=3D"border:1px solid rgb(187,187,187);wo=
rd-wrap:break-word;background-color:rgb(250,250,250)"><code><div><span styl=
e=3D"color:#008">template</span><span style=3D"color:#660">&lt;</span><span=
 style=3D"color:#008">class</span><span style=3D"color:#000"> </span><span =
style=3D"color:#606">Key_type</span><span style=3D"color:#660">,</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#606">Compare</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#606">Comparator</span=
><span style=3D"color:#000"> </span><span style=3D"color:#660">=3D</span><s=
pan style=3D"color:#000"> std</span><span style=3D"color:#660">::</span><sp=
an style=3D"color:#000">equal_to</span><span style=3D"color:#660">&lt;</spa=
n><span style=3D"color:#606">Key_type</span><span style=3D"color:#660">&gt;=
</span><span style=3D"color:#000"> </span><span style=3D"color:#660">&gt;</=
span><span style=3D"color:#000"><br></span><span style=3D"color:#008">struc=
t</span><span style=3D"color:#000"> iterator </span><span style=3D"color:#6=
60">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </sp=
an><span style=3D"color:#800">//other code...</span><span style=3D"color:#0=
00"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">const=
</span><span style=3D"color:#000"> </span><span style=3D"color:#606">Key_ty=
pe</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#000">=
 key</span><span style=3D"color:#660">()</span><span style=3D"color:#000"> =
</span><span style=3D"color:#008">const</span><font color=3D"#666600"><span=
 style=3D"color:#000"> </span><span style=3D"color:#660">{</span></font><sp=
an style=3D"color:#000"> </span><span style=3D"color:#800">//getter</span><=
span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 </span><span style=3D"color:#008">return</span><span style=3D"co=
lor:#000"> m_value</span><span style=3D"color:#660">;</span><span style=3D"=
color:#000"> </span><span style=3D"color:#800">//</span><font color=3D"#000=
000"><span style=3D"color:#800">call conversion operator</span><span style=
=3D"color:#000"><br></span></font><span style=3D"color:#000">=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span style=3D"colo=
r:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">c=
onst</span><span style=3D"color:#000"> </span><span style=3D"color:#606">Ke=
y_type</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#0=
00"> key</span><span style=3D"color:#660">(</span><span style=3D"color:#008=
">const</span><span style=3D"color:#000"> </span><span style=3D"color:#606"=
>Key_type</span><span style=3D"color:#660">&amp;</span><span style=3D"color=
:#000">x</span><span style=3D"color:#660">)</span><span style=3D"color:#000=
"> </span><span style=3D"color:#660">{</span><span style=3D"color:#000"> </=
span><span style=3D"color:#800">//setter</span><span style=3D"color:#000"><=
br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span sty=
le=3D"color:#008">return</span><span style=3D"color:#000"> m_value </span><=
span style=3D"color:#660">=3D</span><span style=3D"color:#000"> x</span><sp=
an style=3D"color:#660">;</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#800">//call copy assignment operator of wrapper class</span><=
span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span styl=
e=3D"color:#660">}</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#008">private</span><span style=3D"color:#660">:</span><span styl=
e=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 const_to_comparison</span>=
<span style=3D"color:#660">&lt;</span><span style=3D"color:#606">Key_type</=
span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#606">Comparator</span><span style=3D"color:#660">&gt;=
</span><span style=3D"color:#000"> m_value<br></span><span style=3D"color:#=
660">};</span><font color=3D"#666600"></font></div></code></div></div><div>=
<br></div><div>(The name &#39;key&#39; isn&#39;t the real function name, fo=
r map iterator it will be &#39;first&#39;, and for the set iterator it will=
 be operator* for getter and set (maybe not a good name in this case) for s=
etter)</div><div>It is possible to be made compatible with other versions b=
ut will make the container to hold another public member for the converted =
type which takes twice the memory it used to.</div><div>So maybe the first =
option where this wrapper class is public is better (at least in my opinion=
).</div><div>Maybe there are other places this const-like access can be use=
d.</div><div>Well, the wrapper looks basically like this:</div><div><br></d=
iv><div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;bac=
kground-color:rgb(250,250,250)"><code><div><span style=3D"color:#008">names=
pace</span><span style=3D"color:#000"> std </span><span style=3D"color:#660=
">{</span><span style=3D"color:#000"><br></span><span style=3D"color:#008">=
template</span><span style=3D"color:#660">&lt;</span><span style=3D"color:#=
008">class</span><span style=3D"color:#000"> _Kty</span><span style=3D"colo=
r:#660">,</span><span style=3D"color:#000"> </span><span style=3D"color:#60=
6">Compare</span><span style=3D"color:#000"> _Pr </span><span style=3D"colo=
r:#660">=3D</span><span style=3D"color:#000"> std</span><span style=3D"colo=
r:#660">::</span><span style=3D"color:#000">equal_to</span><span style=3D"c=
olor:#660">&lt;</span><span style=3D"color:#000">_Kty</span><span style=3D"=
color:#660">&gt;</span><span style=3D"color:#000"> </span><span style=3D"co=
lor:#660">&gt;</span><span style=3D"color:#000"><br></span><span style=3D"c=
olor:#008">class</span><span style=3D"color:#000"> const_to_comparison </sp=
an><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0=
 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typedef</span><span=
 style=3D"color:#000"> const_to_comparison</span><span style=3D"color:#660"=
>&lt;</span><span style=3D"color:#000">_Kty</span><span style=3D"color:#660=
">,</span><span style=3D"color:#000"> _Pr</span><span style=3D"color:#660">=
&gt;</span><span style=3D"color:#000"> _Myt</span><span style=3D"color:#660=
">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span=
><span style=3D"color:#008">typedef</span><span style=3D"color:#000"> _Kty =
key_type</span><span style=3D"color:#660">;</span><span style=3D"color:#000=
"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typedef=
</span><span style=3D"color:#000"> _Pr key_compare</span><span style=3D"col=
or:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0=
 </span><span style=3D"color:#008">static</span><span style=3D"color:#000">=
 </span><span style=3D"color:#008">const</span><span style=3D"color:#000"> =
key_compare comp </span><span style=3D"color:#660">=3D</span><span style=3D=
"color:#000"> _Pr</span><span style=3D"color:#660">();</span><span style=3D=
"color:#000"><br></span><span style=3D"color:#008">public</span><span style=
=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0=
 =C2=A0 </span><span style=3D"color:#008">constexpr</span><span style=3D"co=
lor:#000"> const_to_comparison</span><span style=3D"color:#660">()</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#660">=3D</span><span=
 style=3D"color:#000"> </span><span style=3D"color:#008">default</span><spa=
n style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0=
 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</span><span styl=
e=3D"color:#000"> const_to_comparison</span><span style=3D"color:#660">(</s=
pan><span style=3D"color:#008">const</span><span style=3D"color:#000"> key_=
type</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#000=
"> key</span><span style=3D"color:#660">)</span><span style=3D"color:#000">=
 </span><span style=3D"color:#660">:</span><span style=3D"color:#000"> m_va=
lue</span><span style=3D"color:#660">(</span><span style=3D"color:#000">key=
</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#660">{}</span><span style=3D"color:#000"><br>=C2=A0=
 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</span><sp=
an style=3D"color:#000"> const_to_comparison</span><span style=3D"color:#66=
0">(</span><span style=3D"color:#008">const</span><span style=3D"color:#000=
"> _Myt</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#=
000"> other</span><span style=3D"color:#660">)</span><span style=3D"color:#=
000"> </span><span style=3D"color:#660">:</span><span style=3D"color:#000">=
 m_value</span><span style=3D"color:#660">(</span><span style=3D"color:#000=
">other</span><span style=3D"color:#660">.</span><span style=3D"color:#000"=
>key</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>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</sp=
an><span style=3D"color:#000"> const_to_comparison</span><span style=3D"col=
or:#660">(</span><span style=3D"color:#008">const</span><span style=3D"colo=
r:#000"> _Myt</span><span style=3D"color:#660">&amp;&amp;</span><span style=
=3D"color:#000"> other</span><span style=3D"color:#660">)</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">:</span><span style=3D"c=
olor:#000"> m_value</span><span style=3D"color:#660">(</span><span style=3D=
"color:#000">other</span><span style=3D"color:#660">.</span><span style=3D"=
color:#000">key</span><span style=3D"color:#660">)</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#660">{}</span><span style=3D"color:#=
000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</span=
><span style=3D"color:#660">&amp;</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#008">operator</span><span style=3D"color:#660">=3D(</=
span><span style=3D"color:#000">const_to_comparison</span><span style=3D"co=
lor:#660">&amp;&amp;</span><span style=3D"color:#000"> other</span><span st=
yle=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0=
 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">if</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#660">(!</span>=
<span style=3D"color:#000">comp</span><span style=3D"color:#660">(</span><s=
pan style=3D"color:#000">m_value</span><span style=3D"color:#660">,</span><=
span style=3D"color:#000"> other</span><span style=3D"color:#660">.</span><=
span style=3D"color:#000">m_value</span><span style=3D"color:#660">))</span=
><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0std</span><span style=3D"co=
lor:#660">::</span><span style=3D"color:#000">bad_exception</span><span sty=
le=3D"color:#660">(</span><span style=3D"color:#080">&quot;can&#39;t change=
 this value&quot;</span><span style=3D"color:#660">);</span><span style=3D"=
color:#000"> </span><span style=3D"color:#800">//colud be any other excepti=
on or simply do nothing</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 m_value </span><span style=3D"col=
or:#660">=3D</span><span style=3D"color:#000"> other</span><span style=3D"c=
olor:#660">.</span><span style=3D"color:#000">m_value</span><span style=3D"=
color:#660">;</span><span style=3D"color:#000"> </span><span style=3D"color=
:#800">//calling move operator=3D</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span st=
yle=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</span><span style=
=3D"color:#660">&amp;</span><span style=3D"color:#000"> </span><span style=
=3D"color:#008">operator</span><span style=3D"color:#660">=3D(</span><span =
style=3D"color:#000">const_to_comparison</span><span style=3D"color:#660">&=
amp;</span><span style=3D"color:#000"> other</span><span style=3D"color:#66=
0">)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{<=
/span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">if</span><span style=3D=
"color:#000"> </span><span style=3D"color:#660">(!</span><span style=3D"col=
or:#000">comp</span><span style=3D"color:#660">(</span><span style=3D"color=
:#000">m_value</span><span style=3D"color:#660">,</span><span style=3D"colo=
r:#000"> other</span><span style=3D"color:#660">.</span><span style=3D"colo=
r:#000">m_value</span><span style=3D"color:#660">))</span><span style=3D"co=
lor:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0std</span><span style=3D"color:#660">::</spa=
n><span style=3D"color:#000">bad_exception</span><span style=3D"color:#660"=
>(</span><span style=3D"color:#080">&quot;can&#39;t change this value&quot;=
</span><span style=3D"color:#660">);</span><span style=3D"color:#000"> </sp=
an><span style=3D"color:#800">//colud be any other exception or simply do n=
othing</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 m_value </span><span style=3D"color:#660">=3D</spa=
n><span style=3D"color:#000"> other</span><span style=3D"color:#660">.</spa=
n><span style=3D"color:#000">m_value</span><span style=3D"color:#660">;</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#800">//calling =
copy operator=3D</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color:#660">}</span><span style=3D"color:#000"=
><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">operator=
</span><span style=3D"color:#000"> </span><span style=3D"color:#008">const<=
/span><span style=3D"color:#000"> _Kty</span><span style=3D"color:#660">&am=
p;()</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{<=
/span><span style=3D"color:#000"> </span><span style=3D"color:#800">//for c=
asting to the container&#39;s value_type inside the iterator</span><span st=
yle=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 </span><span style=3D"color:#008">return</span><span style=3D"color:#00=
0"> m_value</span><span style=3D"color:#660">;</span><span style=3D"color:#=
000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660">}</s=
pan><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span=
 style=3D"color:#660">~</span><span style=3D"color:#000">const_to_compariso=
n</span><span style=3D"color:#660">()</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> </span=
><span style=3D"color:#008">default</span><span style=3D"color:#660">;</spa=
n><span style=3D"color:#000"><br></span><span style=3D"color:#008">private<=
/span><span style=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 key_type m_value</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></span><span style=3D"color:#660">}</=
span></div></code></div><div style=3D"font-family:monospace;background-colo=
r:rgb(250,250,250)"><br></div><div>For unordered containers this obviously =
wouldn&#39;t work since the hash value would change every time the key chan=
ges and so will the position in the container, and this whole mechanism wil=
l fail.</div><div>Therefore the hash value must remain constant after equal=
 key replacement, so I tried to solve it the simplest way I could think of =
(I don&#39;t really like this solution so feel free to rip it to shreds):</=
div><div>Save the hash value of the original object in another field and ov=
erload std::hash of this wrapper class to return this field.</div><div>Some=
thing like this:</div><div style=3D"border:1px solid rgb(187,187,187);word-=
wrap:break-word;background-color:rgb(250,250,250)"><code><div><span style=
=3D"color:#000"><br></span><span style=3D"color:#008">namespace</span><span=
 style=3D"color:#000"> std </span><span style=3D"color:#660">{</span><span =
style=3D"color:#000"><br></span><span style=3D"color:#008">template</span><=
span style=3D"color:#660">&lt;</span><span style=3D"color:#008">class</span=
><span style=3D"color:#000"> _Kty</span><span style=3D"color:#660">,</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#606">Compare</span=
><span style=3D"color:#000"> _Pr </span><span style=3D"color:#660">=3D</spa=
n><span style=3D"color:#000"> std</span><span style=3D"color:#660">::</span=
><span style=3D"color:#000">equal_to</span><span style=3D"color:#660">&lt;<=
/span><span style=3D"color:#000">_Kty</span><span style=3D"color:#660">&gt;=
,</span><span style=3D"color:#000"> </span><span style=3D"color:#606">Hash<=
/span><span style=3D"color:#000"> _Hasher </span><span style=3D"color:#660"=
>=3D</span><span style=3D"color:#000"> std</span><span style=3D"color:#660"=
>::</span><span style=3D"color:#000">hash</span><span style=3D"color:#660">=
&lt;</span><span style=3D"color:#000">_Kty</span><span style=3D"color:#660"=
>&gt;</span><span style=3D"color:#000"> </span><span style=3D"color:#660">&=
gt;</span><span style=3D"color:#000"><br></span><span style=3D"color:#008">=
class</span><span style=3D"color:#000"> const_to_comparison_and_hash_value =
</span><span style=3D"color:#660">:</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#008">public</span><span style=3D"color:#000"> const=
_to_comparison </span><span style=3D"color:#660">&lt;</span><span style=3D"=
color:#000"> _Kty</span><span style=3D"color:#660">,</span><span style=3D"c=
olor:#000"> _Pr </span><span style=3D"color:#660">&gt;</span><span style=3D=
"color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"colo=
r:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">t=
ypedef</span><span style=3D"color:#000"> const_to_comparison</span><span st=
yle=3D"color:#660">&lt;</span><span style=3D"color:#000"> _Kty</span><span =
style=3D"color:#660">,</span><span style=3D"color:#000"> _Pr</span><span st=
yle=3D"color:#660">&gt;</span><span style=3D"color:#000"> _Mybase</span><sp=
an style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typedef</span><span sty=
le=3D"color:#000"> const_to_comparison_and_hash_value</span><span style=3D"=
color:#660">&lt;</span><span style=3D"color:#000">_Kty</span><span style=3D=
"color:#660">,</span><span style=3D"color:#000"> _Pr</span><span style=3D"c=
olor:#660">,</span><span style=3D"color:#000"> _Hasher</span><span style=3D=
"color:#660">&gt;</span><span style=3D"color:#000"> _Myt</span><span style=
=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0=
 =C2=A0 </span><span style=3D"color:#008">typedef</span><span style=3D"colo=
r:#000"> _Kty key_type</span><span style=3D"color:#660">;</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color=
:#008">typedef</span><span style=3D"color:#000"> _Pr key_compare</span><spa=
n style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0=
 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typedef</span><span style=
=3D"color:#000"> _Hasher key_hash</span><span style=3D"color:#660">;</span>=
<span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span sty=
le=3D"color:#008">static</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#008">const</span><span style=3D"color:#000"> key_hash hash </s=
pan><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> _Hashe=
r</span><span style=3D"color:#660">();</span><span style=3D"color:#000"><br=
></span><span style=3D"color:#008">public</span><span style=3D"color:#660">=
:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><=
span style=3D"color:#008">constexpr</span><span style=3D"color:#000"> const=
_to_comparison_and_hash_value</span><span style=3D"color:#660">()</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#660">:</span><span st=
yle=3D"color:#000"> _Mybase</span><span style=3D"color:#660">()</span><span=
 style=3D"color:#000"> </span><span style=3D"color:#660">{}</span><span sty=
le=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"col=
or:#008">constexpr</span><span style=3D"color:#000"> const_to_comparison_an=
d_hash_value</span><span style=3D"color:#660">(</span><span style=3D"color:=
#008">const</span><span style=3D"color:#000"> key_type</span><span style=3D=
"color:#660">&amp;</span><span style=3D"color:#000"> other</span><span styl=
e=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"=
color:#660">:</span><span style=3D"color:#000"> _Mybase</span><span style=
=3D"color:#660">(</span><span style=3D"color:#000">other</span><span style=
=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#660">{}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 </span><span style=3D"color:#008">constexpr</span><span style=3D"color:=
#000"> const_to_comparison_and_hash_value</span><span style=3D"color:#660">=
(</span><span style=3D"color:#008">const</span><span style=3D"color:#000"> =
_Mybase</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#=
000"> other</span><span style=3D"color:#660">)</span><span style=3D"color:#=
000"> </span><span style=3D"color:#660">:</span><span style=3D"color:#000">=
 _Mybase</span><span style=3D"color:#660">(</span><span style=3D"color:#000=
">other</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=
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</s=
pan><span style=3D"color:#000"> const_to_comparison_and_hash_value</span><s=
pan style=3D"color:#660">(</span><span style=3D"color:#008">const</span><sp=
an style=3D"color:#000"> _Myt</span><span style=3D"color:#660">&amp;</span>=
<span style=3D"color:#000"> other</span><span style=3D"color:#660">)</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#660">:</span><span=
 style=3D"color:#000"> _Mybase</span><span style=3D"color:#660">(</span><sp=
an style=3D"color:#000">other</span><span style=3D"color:#660">)</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#660">{}</span><span st=
yle=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"co=
lor:#008">constexpr</span><span style=3D"color:#000"> const_to_comparison_a=
nd_hash_value</span><span style=3D"color:#660">(</span><span style=3D"color=
:#008">const</span><span style=3D"color:#000"> _Myt</span><span style=3D"co=
lor:#660">&amp;&amp;</span><span style=3D"color:#000"> other</span><span st=
yle=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">:</span><span style=3D"color:#000"> _Mybase</span><span sty=
le=3D"color:#660">(</span><span style=3D"color:#000">other</span><span styl=
e=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"=
color:#660">{}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 _Myt</span><span style=3D"color:#660">&amp;</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#008">operator</span><span style=3D"c=
olor:#660">=3D(</span><span style=3D"color:#008">const</span><span style=3D=
"color:#000"> _Myt</span><span style=3D"color:#660">&amp;</span><span style=
=3D"color:#000"> other</span><span style=3D"color:#660">)</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"c=
olor:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </sp=
an><span style=3D"color:#008">this</span><span style=3D"color:#660">-&gt;</=
span><span style=3D"color:#000">_Mybase</span><span style=3D"color:#660">::=
</span><span style=3D"color:#008">operator</span><span style=3D"color:#660"=
>=3D((</span><span style=3D"color:#008">const</span><span style=3D"color:#0=
00"> _Mybase</span><span style=3D"color:#660">&amp;)</span><span style=3D"c=
olor:#000">other</span><span style=3D"color:#660">);</span><span style=3D"c=
olor:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660=
">}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</=
span><span style=3D"color:#660">&amp;</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#008">operator</span><span style=3D"color:#660">=
=3D(</span><span style=3D"color:#008">const</span><span style=3D"color:#000=
"> _Myt</span><span style=3D"color:#660">&amp;&amp;</span><span style=3D"co=
lor:#000"> other</span><span style=3D"color:#660">)</span><span style=3D"co=
lor:#000"> </span><span style=3D"color:#660">{</span><span style=3D"color:#=
000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><spa=
n style=3D"color:#008">this</span></div></code></div></div>...</blockquote>=
</div></div></blockquote></blockquote></div></div></div></blockquote></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&quot; 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_6666_1771605933.1436975942165--
------=_Part_6665_2086303566.1436975942164--

.


Author: Omer Rosler <omer.rosler@gmail.com>
Date: Wed, 15 Jul 2015 09:15:49 -0700 (PDT)
Raw View
------=_Part_6529_170840057.1436976949860
Content-Type: multipart/alternative;
 boundary="----=_Part_6530_624566870.1436976949861"

------=_Part_6530_624566870.1436976949861
Content-Type: text/plain; charset=UTF-8

I think you misunderstood me :)
I'm not talking about examples, I'm talking about the fact that the hasher
here depends only on the comparator, so defining it seems redundant .
Basically I'm looking for a general hasher of this wrapper, based on a
comparator and the hasher of the underlying type. Something like:
template<class Key,class Comp, class Hahser = std::hash<Key> >
struct hash<const_wrapper<Key, Comp, Hasher> > {
     size_t operator()(const const_wrapper<Key, Comp, Hasher>&) {/*some
magic...*/}
}
(Not specializing this template, but having a general definition)
And let the user define the comparator and the hasher of the underlying
type only, as it is today.
I don't want the fact that the objects stored in the map can be changed to
make the user write a diffrent code.
If something like this is possible I think it's worthy as a library
extension.

On Wednesday, July 15, 2015 at 6:59:02 PM UTC+3, Edward Catmur wrote:
>
> In the cases where it's legitimate to modify the key (generally a record
> where only some fields participate in the key identity) one has to provide
> a hasher and comparator expressing that restricted identity concept; that's
> what my example was intended to model. There's no need to provide another
> hasher or comparator.
>
> Perhaps I misunderstood your intent; could you provide a simple use case
> like I did above?
>
> On Wednesday, 15 July 2015 16:49:50 UTC+1, Omer Rosler wrote:
>>
>> Of course I want to hash on the underlying type, but I don't want to
>> create another function to do it for me like in your example. In the
>> original suggstion the function simply called a hasher once (on the real
>> object), saved the value and returned it as if the object is const (this
>> all done in a single template and not comparator specific like in your
>> example), but this takes more momery (sizeof(size_t) per object).
>> I see the problem in using static hashers, maybe a few static functions
>> that can change the state of the hasher.
>> Well, if this limited-access class is not that common than this
>> discussion is pointless anyway...
>>
>> On Wednesday, July 15, 2015 at 4:50:27 PM UTC+3, Edward Catmur wrote:
>>>
>>> On Wednesday, 15 July 2015 13:44:04 UTC+1, Omer Rosler wrote:
>>>>
>>>> First, Thanks for the feedback.
>>>> The reason I used the default value of the Comparator to be
>>>> std::equal_to is because I wanted this class to be a stand-alone,
>>>> regardless of containers; containers will use it with !comp(lhs, rhs)
>>>> && !comp(rhs, lhs) instead of this default value as you mentionted.
>>>> I did not know about the mutable keyword, this simplifies things alot,
>>>> so thank you for that.
>>>> About the unordered containers: I don't want to define a new hash
>>>> function every time I use an unordered container with this type, although I
>>>> can't see a solution that doesn't take more memory (or any possible way of
>>>> making a template hasher that performs a hash on a representative for
>>>> general type and general comparator).
>>>>
>>>
>>> Why not just use the hash on the underlying type?
>>>
>>>
>>>> If a limited access wrapper like this is a common nescessity (beyond
>>>> mutable keys in associative containers) then maybe it is worth standarizing
>>>> on it's own.
>>>> If so, the comparator needs not to come from a container, so using a
>>>> static member is probably the solution.
>>>>
>>>
>>> The problem there is that hashers can have state (e.g. a function
>>> pointer or a type-erased function wrapper), so a static member won't work.
>>> I can't think of any use other than associative containers, so you might as
>>> well use the container's comparator and hasher.
>>>
>>>
>>>> So, is this limited access wrapper worth standarizing?
>>>>
>>>> On Tuesday, July 14, 2015 at 11:23:45 PM UTC+3, Omer Rosler wrote:
>>>>>
>>>>> This is the first time I share my ideas about C++, so don't be too
>>>>> harsh :)
>>>>> This post is an attempt to partially solve the problem of key
>>>>> replacement  in (unordered) associative containers such as
>>>>> (unordered_)(multi)map, (unordered_)(multi)set* when the object
>>>>> doesn't move inside the container after replacement and the value *up
>>>>> to the comparator* is the same.
>>>>> *The braces () mean optiopnal.
>>>>> Note that in ordered containers if the value doesn't change (up to the
>>>>> comparator) so does the position of the object; in unordered this gets
>>>>> trickier, but we'll get to that later.
>>>>> My aproach is to create an intermediate class that provides a
>>>>> const-like access to a object but allows changing it if a comparator yields
>>>>> true (so the complexity of the assignment operator is the maximum of the
>>>>> complexity of the object type's assignemnt operator, and the comparator's
>>>>> complexity).
>>>>> In case of setting a diffrent value this class can either throw some
>>>>> exception or simply do nothing (up for debate).
>>>>> By using this class inside the underlying RB tree as the value type
>>>>> (instead of a simple const type) it will allow iterators to change the
>>>>> value of the key they hold by calling the wrapper class's assignemnt
>>>>> iterator.
>>>>> I haven't decided whether it's smart to make this class public and
>>>>> change the containers' value type (meaning: big diffrence from older
>>>>> versions for all 8 containers, although the conversion operator makes old
>>>>> code work all the same), or simply make it private and convert to
>>>>> container's value type inside the iterators which will now have setter
>>>>> functions.
>>>>> The second option has major downsides: The current iterators interface
>>>>> needs to be changed, instead of holding const key as a public member (like
>>>>> it does now), it will hold this wrapper class as a private/protected
>>>>> member, and accessing it must be done using a function call to a getter
>>>>> that calls a conversion operator (so access is using funtion calls only,
>>>>> instead of accessing a public member):
>>>>> template<class Key_type, Compare Comparator = std::equal_to<Key_type>
>>>>> >
>>>>> struct iterator {
>>>>>         //other code...
>>>>>         const Key_type& key() const { //getter
>>>>>                 return m_value; //call conversion operator
>>>>>         }
>>>>>         const Key_type& key(const Key_type&x) { //setter
>>>>>                 return m_value = x; //call copy assignment operator
>>>>> of wrapper class
>>>>>         }
>>>>> private:
>>>>>         const_to_comparison<Key_type, Comparator> m_value
>>>>> };
>>>>>
>>>>> (The name 'key' isn't the real function name, for map iterator it will
>>>>> be 'first', and for the set iterator it will be operator* for getter and
>>>>> set (maybe not a good name in this case) for setter)
>>>>> It is possible to be made compatible with other versions but will make
>>>>> the container to hold another public member for the converted type which
>>>>> takes twice the memory it used to.
>>>>> So maybe the first option where this wrapper class is public is better
>>>>> (at least in my opinion).
>>>>> Maybe there are other places this const-like access can be used.
>>>>> Well, the wrapper looks basically like this:
>>>>>
>>>>> namespace std {
>>>>> template<class _Kty, Compare _Pr = std::equal_to<_Kty> >
>>>>> class const_to_comparison {
>>>>>         typedef const_to_comparison<_Kty, _Pr> _Myt;
>>>>>         typedef _Kty key_type;
>>>>>         typedef _Pr key_compare;
>>>>>         static const key_compare comp = _Pr();
>>>>> public:
>>>>>         constexpr const_to_comparison() = default;
>>>>>         constexpr const_to_comparison(const key_type& key) : m_value(
>>>>> key) {}
>>>>>         constexpr const_to_comparison(const _Myt& other) : m_value(
>>>>> other.key) {}
>>>>>         constexpr const_to_comparison(const _Myt&& other) : m_value(
>>>>> other.key) {}
>>>>>                 _Myt& operator=(const_to_comparison&& other) {
>>>>>                 if (!comp(m_value, other.m_value))
>>>>>                          std::bad_exception("can't change this value"
>>>>> ); //colud be any other exception or simply do nothing
>>>>>                 m_value = other.m_value; //calling move operator=
>>>>>         }
>>>>>         _Myt& operator=(const_to_comparison& other) {
>>>>>                 if (!comp(m_value, other.m_value))
>>>>>                          std::bad_exception("can't change this value"
>>>>> ); //colud be any other exception or simply do nothing
>>>>>                 m_value = other.m_value; //calling copy operator=
>>>>>         }
>>>>>         operator const _Kty&() { //for casting to the container's
>>>>> value_type inside the iterator
>>>>>                 return m_value;
>>>>>         }
>>>>>         ~const_to_comparison() = default;
>>>>> private:
>>>>>         key_type m_value;
>>>>> };
>>>>> }
>>>>>
>>>>> For unordered containers this obviously wouldn't work since the hash
>>>>> value would change every time the key changes and so will the position in
>>>>> the container, and this whole mechanism will fail.
>>>>> Therefore the hash value must remain constant after equal key
>>>>> replacement, so I tried to solve it the simplest way I could think of (I
>>>>> don't really like this solution so feel free to rip it to shreds):
>>>>> Save the hash value of the original object in another field and
>>>>> overload std::hash of this wrapper class to return this field.
>>>>> Something like this:
>>>>>
>>>>> namespace std {
>>>>> template<class _Kty, Compare _Pr = std::equal_to<_Kty>, Hash _Hasher =
>>>>> std::hash<_Kty> >
>>>>> class const_to_comparison_and_hash_value : public const_to_comparison
>>>>> < _Kty, _Pr > {
>>>>>         typedef const_to_comparison< _Kty, _Pr> _Mybase;
>>>>>         typedef const_to_comparison_and_hash_value<_Kty, _Pr, _Hasher>
>>>>> _Myt;
>>>>>         typedef _Kty key_type;
>>>>>         typedef _Pr key_compare;
>>>>>         typedef _Hasher key_hash;
>>>>>         static const key_hash hash = _Hasher();
>>>>> public:
>>>>>         constexpr const_to_comparison_and_hash_value() : _Mybase() {}
>>>>>         constexpr const_to_comparison_and_hash_value(const key_type&
>>>>> other) : _Mybase(other) {}
>>>>>         constexpr const_to_comparison_and_hash_value(const _Mybase&
>>>>> other) : _Mybase(other) {}
>>>>>         constexpr const_to_comparison_and_hash_value(const _Myt& other
>>>>> ) : _Mybase(other) {}
>>>>>         constexpr const_to_comparison_and_hash_value(const _Myt&&
>>>>> other) : _Mybase(other) {}
>>>>>         _Myt& operator=(const _Myt& other) {
>>>>>                 this->_Mybase::operator=((const _Mybase&)other);
>>>>>         }
>>>>>         _Myt& operator=(const _Myt&& other) {
>>>>>                this
>>>>> ...
>>>>
>>>>

--

---
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_6530_624566870.1436976949861
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">I think you misunderstood me :)<div>I&#39;m not talking ab=
out examples, I&#39;m talking about the fact that the hasher here depends o=
nly on the comparator, so defining it seems redundant . Basically I&#39;m l=
ooking for a general hasher of this wrapper, based on a comparator and the =
hasher of the underlying type. Something like:</div><div><div class=3D"pret=
typrint" style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-wo=
rd; background-color: rgb(250, 250, 250);"><code class=3D"prettyprint"><div=
 class=3D"subprettyprint"><font color=3D"#660066"><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">template</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">class</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by=
-prettify">Key</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">,</span><span style=3D"color: #008;" class=3D"styled-by-prettify">class=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #606;" class=3D"styled-by-prettify">Comp</span><span st=
yle=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: #008=
;" class=3D"styled-by-prettify">class</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #606;" class=3D"st=
yled-by-prettify">Hahser</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> s=
td</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify">hash</span><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=
=3D"color: #606;" class=3D"styled-by-prettify">Key</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">&gt;</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">&gt;</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-=
by-prettify">struct</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> hash</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">&lt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">co=
nst_wrapper</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>&lt;</span><span style=3D"color: #606;" class=3D"styled-by-prettify">Key</=
span><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: #606;" class=3D"styled-by-prettify">Comp</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" class=
=3D"styled-by-prettify">Hasher</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">&gt;</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =
=C2=A0size_t </span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">operator</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>()(</span><span style=3D"color: #008;" class=3D"styled-by-prettify">const<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> const_wrap=
per</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</s=
pan><span style=3D"color: #606;" class=3D"styled-by-prettify">Key</span><sp=
an 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=
: #606;" class=3D"styled-by-prettify">Comp</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: #606;" class=3D"style=
d-by-prettify">Hasher</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">&gt;&amp;)</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: #800;" class=3D"styled-by-prettify">/*some =
magic...*/</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br></span></font></div>=
</code></div>(Not specializing this template, but having a general definiti=
on)</div><div>And let the user define the comparator and the hasher of the =
underlying type only, as it is today.</div><div>I don&#39;t want the fact t=
hat the objects stored in the map can be changed to make the user write a d=
iffrent code.<br>If something like this is possible I think it&#39;s worthy=
 as a library extension.<br><br>On Wednesday, July 15, 2015 at 6:59:02 PM U=
TC+3, Edward Catmur 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">In the cases where it&#39;s legitimate to modify the key (gene=
rally a record where only some fields participate in the key identity) one =
has to provide a hasher and comparator expressing that restricted identity =
concept; that&#39;s what my example was intended to model. There&#39;s no n=
eed to provide another hasher or comparator.<div><br></div><div>Perhaps I m=
isunderstood your intent; could you provide a simple use case like I did ab=
ove?<br><br>On Wednesday, 15 July 2015 16:49:50 UTC+1, Omer Rosler  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">Of course I want to=
 hash on the underlying type, but I don&#39;t want to create another functi=
on to do it for me like in your example. In the original suggstion the func=
tion simply called a hasher once (on the real object), saved the value and =
returned it as if the object is const (this all done in a single template a=
nd not comparator specific like in your example), but this takes more momer=
y (sizeof(size_t) per object).<div>I see the problem in using static hasher=
s, maybe a few static functions that can change the state of the hasher.</d=
iv><div>Well, if this limited-access class is not that common than this dis=
cussion is pointless anyway...</div><div><br><div>On Wednesday, July 15, 20=
15 at 4:50:27 PM UTC+3, Edward Catmur wrote:<blockquote class=3D"gmail_quot=
e" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-l=
eft:1ex">On Wednesday, 15 July 2015 13:44:04 UTC+1, Omer Rosler  wrote:<blo=
ckquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-le=
ft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">First, Thanks for the =
feedback.<div>The reason I used the default value of the Comparator to be s=
td::equal_to is because I wanted this class to be a stand-alone, regardless=
 of containers; containers will use it with=C2=A0<span style=3D"font-family=
:&#39;courier new&#39;,monospace">!comp(lhs, rhs) &amp;&amp; !comp(rhs, lhs=
)</span>=C2=A0instead of this default value as you mentionted.</div><div>I =
did not know about the mutable keyword, this simplifies things alot, so tha=
nk you for that.</div><div>About the unordered containers: I don&#39;t want=
 to define a new hash function every time I use an unordered container with=
 this type, although I can&#39;t see a solution that doesn&#39;t take more =
memory (or any possible way of making a template hasher that performs a has=
h on a representative for general type and general comparator).</div></div>=
</blockquote><div><br></div><div>Why not just use the hash on the underlyin=
g type?</div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div =
dir=3D"ltr"><div>If a limited access wrapper like this is a common nescessi=
ty (beyond mutable keys in associative containers) then maybe it is worth s=
tandarizing on it&#39;s own.</div><div>If so, the comparator needs not to c=
ome from a container, so using a static member is probably the solution.</d=
iv></div></blockquote><div><br></div><div>The problem there is that hashers=
 can have state (e.g. a function pointer or a type-erased function wrapper)=
, so a static member won&#39;t work. I can&#39;t think of any use other tha=
n associative containers, so you might as well use the container&#39;s comp=
arator and hasher.</div><div>=C2=A0</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>So, is this limited access wrapper worth standa=
rizing?<br><br>On Tuesday, July 14, 2015 at 11:23:45 PM UTC+3, Omer Rosler =
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>This is=
 the first time I share my ideas about C++, so don&#39;t be too harsh :)<br=
></div><div>This post is an attempt to partially solve the problem of key r=
eplacement =C2=A0in (unordered) associative containers such as</div><div>(u=
nordered_)(multi)map, (unordered_)(multi)set* when the object doesn&#39;t m=
ove inside the container after replacement and the value <b>up to the compa=
rator</b> is the same.</div><div>*The braces () mean optiopnal.</div><div>N=
ote that in ordered containers if the value doesn&#39;t change (up to the c=
omparator) so does the position of the object; in unordered this gets trick=
ier, but we&#39;ll get to that later.</div><div>My aproach is to create an =
intermediate class that provides a const-like access to a object but allows=
 changing it if a comparator yields true (so the complexity of the assignme=
nt operator is the maximum of the complexity of the object type&#39;s assig=
nemnt operator, and the comparator&#39;s complexity).</div><div>In case of =
setting a diffrent value this class can either throw some exception or simp=
ly do nothing (up for debate).</div><div>By using this class inside the und=
erlying RB tree as the value type (instead of a simple const type) it will =
allow iterators to change the value of the key they hold by calling the wra=
pper class&#39;s assignemnt iterator.</div><div>I haven&#39;t decided wheth=
er it&#39;s smart to make this class public and change the containers&#39; =
value type (meaning: big diffrence from older versions for all 8 containers=
, although the conversion operator makes old code work all the same), or si=
mply make it private and convert to container&#39;s value type inside the i=
terators which will now have setter functions.</div><div>The second option =
has major downsides: The current iterators interface needs to be changed, i=
nstead of holding const key as a public member (like it does now), it will =
hold this wrapper class as a private/protected member, and accessing it mus=
t be done using a function call to a getter that calls a conversion operato=
r (so access is using funtion calls only, instead of accessing a public mem=
ber):</div><div><div style=3D"border:1px solid rgb(187,187,187);word-wrap:b=
reak-word;background-color:rgb(250,250,250)"><code><div><span style=3D"colo=
r:#008">template</span><span style=3D"color:#660">&lt;</span><span style=3D=
"color:#008">class</span><span style=3D"color:#000"> </span><span style=3D"=
color:#606">Key_type</span><span style=3D"color:#660">,</span><span style=
=3D"color:#000"> </span><span style=3D"color:#606">Compare</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#606">Comparator</span><span =
style=3D"color:#000"> </span><span style=3D"color:#660">=3D</span><span sty=
le=3D"color:#000"> std</span><span style=3D"color:#660">::</span><span styl=
e=3D"color:#000">equal_to</span><span style=3D"color:#660">&lt;</span><span=
 style=3D"color:#606">Key_type</span><span style=3D"color:#660">&gt;</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#660">&gt;</span><s=
pan style=3D"color:#000"><br></span><span style=3D"color:#008">struct</span=
><span style=3D"color:#000"> iterator </span><span style=3D"color:#660">{</=
span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><spa=
n style=3D"color:#800">//other code...</span><span style=3D"color:#000"><br=
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">const</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#606">Key_type</spa=
n><span style=3D"color:#660">&amp;</span><span style=3D"color:#000"> key</s=
pan><span style=3D"color:#660">()</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#008">const</span><font color=3D"#666600"><span style=
=3D"color:#000"> </span><span style=3D"color:#660">{</span></font><span sty=
le=3D"color:#000"> </span><span style=3D"color:#800">//getter</span><span s=
tyle=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color:#008">return</span><span style=3D"color:=
#000"> m_value</span><span style=3D"color:#660">;</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#800">//</span><font color=3D"#000000"=
><span style=3D"color:#800">call conversion operator</span><span style=3D"c=
olor:#000"><br></span></font><span style=3D"color:#000">=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span style=3D"color:#=
000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">cons=
t</span><span style=3D"color:#000"> </span><span style=3D"color:#606">Key_t=
ype</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#000"=
> key</span><span style=3D"color:#660">(</span><span style=3D"color:#008">c=
onst</span><span style=3D"color:#000"> </span><span style=3D"color:#606">Ke=
y_type</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#0=
00">x</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> =
</span><span style=3D"color:#660">{</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#800">//setter</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=
=3D"color:#008">return</span><span style=3D"color:#000"> m_value </span><sp=
an style=3D"color:#660">=3D</span><span style=3D"color:#000"> x</span><span=
 style=3D"color:#660">;</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#800">//call copy assignment operator of wrapper class</span><sp=
an style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=
=3D"color:#660">}</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#008">private</span><span style=3D"color:#660">:</span><span styl=
e=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 const_to_comparison</span>=
<span style=3D"color:#660">&lt;</span><span style=3D"color:#606">Key_type</=
span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#606">Comparator</span><span style=3D"color:#660">&gt;=
</span><span style=3D"color:#000"> m_value<br></span><span style=3D"color:#=
660">};</span><font color=3D"#666600"></font></div></code></div></div><div>=
<br></div><div>(The name &#39;key&#39; isn&#39;t the real function name, fo=
r map iterator it will be &#39;first&#39;, and for the set iterator it will=
 be operator* for getter and set (maybe not a good name in this case) for s=
etter)</div><div>It is possible to be made compatible with other versions b=
ut will make the container to hold another public member for the converted =
type which takes twice the memory it used to.</div><div>So maybe the first =
option where this wrapper class is public is better (at least in my opinion=
).</div><div>Maybe there are other places this const-like access can be use=
d.</div><div>Well, the wrapper looks basically like this:</div><div><br></d=
iv><div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;bac=
kground-color:rgb(250,250,250)"><code><div><span style=3D"color:#008">names=
pace</span><span style=3D"color:#000"> std </span><span style=3D"color:#660=
">{</span><span style=3D"color:#000"><br></span><span style=3D"color:#008">=
template</span><span style=3D"color:#660">&lt;</span><span style=3D"color:#=
008">class</span><span style=3D"color:#000"> _Kty</span><span style=3D"colo=
r:#660">,</span><span style=3D"color:#000"> </span><span style=3D"color:#60=
6">Compare</span><span style=3D"color:#000"> _Pr </span><span style=3D"colo=
r:#660">=3D</span><span style=3D"color:#000"> std</span><span style=3D"colo=
r:#660">::</span><span style=3D"color:#000">equal_to</span><span style=3D"c=
olor:#660">&lt;</span><span style=3D"color:#000">_Kty</span><span style=3D"=
color:#660">&gt;</span><span style=3D"color:#000"> </span><span style=3D"co=
lor:#660">&gt;</span><span style=3D"color:#000"><br></span><span style=3D"c=
olor:#008">class</span><span style=3D"color:#000"> const_to_comparison </sp=
an><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0=
 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typedef</span><span=
 style=3D"color:#000"> const_to_comparison</span><span style=3D"color:#660"=
>&lt;</span><span style=3D"color:#000">_Kty</span><span style=3D"color:#660=
">,</span><span style=3D"color:#000"> _Pr</span><span style=3D"color:#660">=
&gt;</span><span style=3D"color:#000"> _Myt</span><span style=3D"color:#660=
">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span=
><span style=3D"color:#008">typedef</span><span style=3D"color:#000"> _Kty =
key_type</span><span style=3D"color:#660">;</span><span style=3D"color:#000=
"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typedef=
</span><span style=3D"color:#000"> _Pr key_compare</span><span style=3D"col=
or:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0=
 </span><span style=3D"color:#008">static</span><span style=3D"color:#000">=
 </span><span style=3D"color:#008">const</span><span style=3D"color:#000"> =
key_compare comp </span><span style=3D"color:#660">=3D</span><span style=3D=
"color:#000"> _Pr</span><span style=3D"color:#660">();</span><span style=3D=
"color:#000"><br></span><span style=3D"color:#008">public</span><span style=
=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0=
 =C2=A0 </span><span style=3D"color:#008">constexpr</span><span style=3D"co=
lor:#000"> const_to_comparison</span><span style=3D"color:#660">()</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#660">=3D</span><span=
 style=3D"color:#000"> </span><span style=3D"color:#008">default</span><spa=
n style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0=
 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</span><span styl=
e=3D"color:#000"> const_to_comparison</span><span style=3D"color:#660">(</s=
pan><span style=3D"color:#008">const</span><span style=3D"color:#000"> key_=
type</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#000=
"> key</span><span style=3D"color:#660">)</span><span style=3D"color:#000">=
 </span><span style=3D"color:#660">:</span><span style=3D"color:#000"> m_va=
lue</span><span style=3D"color:#660">(</span><span style=3D"color:#000">key=
</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#660">{}</span><span style=3D"color:#000"><br>=C2=A0=
 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</span><sp=
an style=3D"color:#000"> const_to_comparison</span><span style=3D"color:#66=
0">(</span><span style=3D"color:#008">const</span><span style=3D"color:#000=
"> _Myt</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#=
000"> other</span><span style=3D"color:#660">)</span><span style=3D"color:#=
000"> </span><span style=3D"color:#660">:</span><span style=3D"color:#000">=
 m_value</span><span style=3D"color:#660">(</span><span style=3D"color:#000=
">other</span><span style=3D"color:#660">.</span><span style=3D"color:#000"=
>key</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>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</sp=
an><span style=3D"color:#000"> const_to_comparison</span><span style=3D"col=
or:#660">(</span><span style=3D"color:#008">const</span><span style=3D"colo=
r:#000"> _Myt</span><span style=3D"color:#660">&amp;&amp;</span><span style=
=3D"color:#000"> other</span><span style=3D"color:#660">)</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">:</span><span style=3D"c=
olor:#000"> m_value</span><span style=3D"color:#660">(</span><span style=3D=
"color:#000">other</span><span style=3D"color:#660">.</span><span style=3D"=
color:#000">key</span><span style=3D"color:#660">)</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#660">{}</span><span style=3D"color:#=
000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</span=
><span style=3D"color:#660">&amp;</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#008">operator</span><span style=3D"color:#660">=3D(</=
span><span style=3D"color:#000">const_to_comparison</span><span style=3D"co=
lor:#660">&amp;&amp;</span><span style=3D"color:#000"> other</span><span st=
yle=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0=
 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">if</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#660">(!</span>=
<span style=3D"color:#000">comp</span><span style=3D"color:#660">(</span><s=
pan style=3D"color:#000">m_value</span><span style=3D"color:#660">,</span><=
span style=3D"color:#000"> other</span><span style=3D"color:#660">.</span><=
span style=3D"color:#000">m_value</span><span style=3D"color:#660">))</span=
><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0std</span><span style=3D"co=
lor:#660">::</span><span style=3D"color:#000">bad_exception</span><span sty=
le=3D"color:#660">(</span><span style=3D"color:#080">&quot;can&#39;t change=
 this value&quot;</span><span style=3D"color:#660">);</span><span style=3D"=
color:#000"> </span><span style=3D"color:#800">//colud be any other excepti=
on or simply do nothing</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 m_value </span><span style=3D"col=
or:#660">=3D</span><span style=3D"color:#000"> other</span><span style=3D"c=
olor:#660">.</span><span style=3D"color:#000">m_value</span><span style=3D"=
color:#660">;</span><span style=3D"color:#000"> </span><span style=3D"color=
:#800">//calling move operator=3D</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span st=
yle=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</span><span style=
=3D"color:#660">&amp;</span><span style=3D"color:#000"> </span><span style=
=3D"color:#008">operator</span><span style=3D"color:#660">=3D(</span><span =
style=3D"color:#000">const_to_comparison</span><span style=3D"color:#660">&=
amp;</span><span style=3D"color:#000"> other</span><span style=3D"color:#66=
0">)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{<=
/span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">if</span><span style=3D=
"color:#000"> </span><span style=3D"color:#660">(!</span><span style=3D"col=
or:#000">comp</span><span style=3D"color:#660">(</span><span style=3D"color=
:#000">m_value</span><span style=3D"color:#660">,</span><span style=3D"colo=
r:#000"> other</span><span style=3D"color:#660">.</span><span style=3D"colo=
r:#000">m_value</span><span style=3D"color:#660">))</span><span style=3D"co=
lor:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0std</span><span style=3D"color:#660">::</spa=
n><span style=3D"color:#000">bad_exception</span><span style=3D"color:#660"=
>(</span><span style=3D"color:#080">&quot;can&#39;t change this value&quot;=
</span><span style=3D"color:#660">);</span><span style=3D"color:#000"> </sp=
an><span style=3D"color:#800">//colud be any other exception or simply do n=
othing</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 m_value </span><span style=3D"color:#660">=3D</spa=
n><span style=3D"color:#000"> other</span><span style=3D"color:#660">.</spa=
n><span style=3D"color:#000">m_value</span><span style=3D"color:#660">;</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#800">//calling =
copy operator=3D</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color:#660">}</span><span style=3D"color:#000"=
><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">operator=
</span><span style=3D"color:#000"> </span><span style=3D"color:#008">const<=
/span><span style=3D"color:#000"> _Kty</span><span style=3D"color:#660">&am=
p;()</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{<=
/span><span style=3D"color:#000"> </span><span style=3D"color:#800">//for c=
asting to the container&#39;s value_type inside the iterator</span><span st=
yle=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 </span><span style=3D"color:#008">return</span><span style=3D"color:#00=
0"> m_value</span><span style=3D"color:#660">;</span><span style=3D"color:#=
000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660">}</s=
pan><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span=
 style=3D"color:#660">~</span><span style=3D"color:#000">const_to_compariso=
n</span><span style=3D"color:#660">()</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> </span=
><span style=3D"color:#008">default</span><span style=3D"color:#660">;</spa=
n><span style=3D"color:#000"><br></span><span style=3D"color:#008">private<=
/span><span style=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 key_type m_value</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></span><span style=3D"color:#660">}</=
span></div></code></div><div style=3D"font-family:monospace;background-colo=
r:rgb(250,250,250)"><br></div><div>For unordered containers this obviously =
wouldn&#39;t work since the hash value would change every time the key chan=
ges and so will the position in the container, and this whole mechanism wil=
l fail.</div><div>Therefore the hash value must remain constant after equal=
 key replacement, so I tried to solve it the simplest way I could think of =
(I don&#39;t really like this solution so feel free to rip it to shreds):</=
div><div>Save the hash value of the original object in another field and ov=
erload std::hash of this wrapper class to return this field.</div><div>Some=
thing like this:</div><div style=3D"border:1px solid rgb(187,187,187);word-=
wrap:break-word;background-color:rgb(250,250,250)"><code><div><span style=
=3D"color:#000"><br></span><span style=3D"color:#008">namespace</span><span=
 style=3D"color:#000"> std </span><span style=3D"color:#660">{</span><span =
style=3D"color:#000"><br></span><span style=3D"color:#008">template</span><=
span style=3D"color:#660">&lt;</span><span style=3D"color:#008">class</span=
><span style=3D"color:#000"> _Kty</span><span style=3D"color:#660">,</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#606">Compare</span=
><span style=3D"color:#000"> _Pr </span><span style=3D"color:#660">=3D</spa=
n><span style=3D"color:#000"> std</span><span style=3D"color:#660">::</span=
><span style=3D"color:#000">equal_to</span><span style=3D"color:#660">&lt;<=
/span><span style=3D"color:#000">_Kty</span><span style=3D"color:#660">&gt;=
,</span><span style=3D"color:#000"> </span><span style=3D"color:#606">Hash<=
/span><span style=3D"color:#000"> _Hasher </span><span style=3D"color:#660"=
>=3D</span><span style=3D"color:#000"> std</span><span style=3D"color:#660"=
>::</span><span style=3D"color:#000">hash</span><span style=3D"color:#660">=
&lt;</span><span style=3D"color:#000">_Kty</span><span style=3D"color:#660"=
>&gt;</span><span style=3D"color:#000"> </span><span style=3D"color:#660">&=
gt;</span><span style=3D"color:#000"><br></span><span style=3D"color:#008">=
class</span><span style=3D"color:#000"> const_to_comparison_and_hash_value =
</span><span style=3D"color:#660">:</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#008">public</span><span style=3D"color:#000"> const=
_to_comparison </span><span style=3D"color:#660">&lt;</span><span style=3D"=
color:#000"> _Kty</span><span style=3D"color:#660">,</span><span style=3D"c=
olor:#000"> _Pr </span><span style=3D"color:#660">&gt;</span><span style=3D=
"color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"colo=
r:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">t=
ypedef</span><span style=3D"color:#000"> const_to_comparison</span><span st=
yle=3D"color:#660">&lt;</span><span style=3D"color:#000"> _Kty</span><span =
style=3D"color:#660">,</span><span style=3D"color:#000"> _Pr</span><span st=
yle=3D"color:#660">&gt;</span><span style=3D"color:#000"> _Mybase</span><sp=
an style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typedef</span><span sty=
le=3D"color:#000"> const_to_comparison_and_hash_value</span><span style=3D"=
color:#660">&lt;</span><span style=3D"color:#000">_Kty</span><span style=3D=
"color:#660">,</span><span style=3D"color:#000"> _Pr</span><span style=3D"c=
olor:#660">,</span><span style=3D"color:#000"> _Hasher</span><span style=3D=
"color:#660">&gt;</span><span style=3D"color:#000"> _Myt</span><span style=
=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0=
 =C2=A0 </span><span style=3D"color:#008">typedef</span><span style=3D"colo=
r:#000"> _Kty key_type</span><span style=3D"color:#660">;</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color=
:#008">typedef</span><span style=3D"color:#000"> _Pr key_compare</span><spa=
n style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0=
 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typedef</span><span style=
=3D"color:#000"> _Hasher key_hash</span><span style=3D"color:#660">;</span>=
<span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span sty=
le=3D"color:#008">static</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#008">const</span><span style=3D"color:#000"> key_hash hash </s=
pan><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> _Hashe=
r</span><span style=3D"color:#660">();</span><span style=3D"color:#000"><br=
></span><span style=3D"color:#008">public</span><span style=3D"color:#660">=
:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><=
span style=3D"color:#008">constexpr</span><span style=3D"color:#000"> const=
_to_comparison_and_hash_value</span><span style=3D"color:#660">()</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#660">:</span><span st=
yle=3D"color:#000"> _Mybase</span><span style=3D"color:#660">()</span><span=
 style=3D"color:#000"> </span><span style=3D"color:#660">{}</span><span sty=
le=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"col=
or:#008">constexpr</span><span style=3D"color:#000"> const_to_comparison_an=
d_hash_value</span><span style=3D"color:#660">(</span><span style=3D"color:=
#008">const</span><span style=3D"color:#000"> key_type</span><span style=3D=
"color:#660">&amp;</span><span style=3D"color:#000"> other</span><span styl=
e=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"=
color:#660">:</span><span style=3D"color:#000"> _Mybase</span><span style=
=3D"color:#660">(</span><span style=3D"color:#000">other</span><span style=
=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#660">{}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 </span><span style=3D"color:#008">constexpr</span><span style=3D"color:=
#000"> const_to_comparison_and_hash_value</span><span style=3D"color:#660">=
(</span><span style=3D"color:#008">const</span><span style=3D"color:#000"> =
_Mybase</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#=
000"> other</span><span style=3D"color:#660">)</span><span style=3D"color:#=
000"> </span><span style=3D"color:#660">:</span><span style=3D"color:#000">=
 _Mybase</span><span style=3D"color:#660">(</span><span style=3D"color:#000=
">other</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=
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</s=
pan><span style=3D"color:#000"> const_to_comparison_and_hash_value</span><s=
pan style=3D"color:#660">(</span><span style=3D"color:#008">const</span><sp=
an style=3D"color:#000"> _Myt</span><span style=3D"color:#660">&amp;</span>=
<span style=3D"color:#000"> other</span><span style=3D"color:#660">)</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#660">:</span><span=
 style=3D"color:#000"> _Mybase</span><span style=3D"color:#660">(</span><sp=
an style=3D"color:#000">other</span><span style=3D"color:#660">)</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#660">{}</span><span st=
yle=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"co=
lor:#008">constexpr</span><span style=3D"color:#000"> const_to_comparison_a=
nd_hash_value</span><span style=3D"color:#660">(</span><span style=3D"color=
:#008">const</span><span style=3D"color:#000"> _Myt</span><span style=3D"co=
lor:#660">&amp;&amp;</span><span style=3D"color:#000"> other</span><span st=
yle=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">:</span><span style=3D"color:#000"> _Mybase</span><span sty=
le=3D"color:#660">(</span><span style=3D"color:#000">other</span><span styl=
e=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"=
color:#660">{}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 _Myt</span><span style=3D"color:#660">&amp;</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#008">operator</span><span style=3D"c=
olor:#660">=3D(</span><span style=3D"color:#008">const</span><span style=3D=
"color:#000"> _Myt</span><span style=3D"color:#660">&amp;</span><span style=
=3D"color:#000"> other</span><span style=3D"color:#660">)</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"c=
olor:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </sp=
an><span style=3D"color:#008">this</span><span style=3D"color:#660">-&gt;</=
span><span style=3D"color:#000">_Mybase</span><span style=3D"color:#660">::=
</span><span style=3D"color:#008">operator</span><span style=3D"color:#660"=
>=3D((</span><span style=3D"color:#008">const</span><span style=3D"color:#0=
00"> _Mybase</span><span style=3D"color:#660">&amp;)</span><span style=3D"c=
olor:#000">other</span><span style=3D"color:#660">);</span><span style=3D"c=
olor:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660=
">}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</=
span><span style=3D"color:#660">&amp;</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#008">operator</span><span style=3D"color:#660">=
=3D(</span><span style=3D"color:#008">const</span><span style=3D"color:#000=
"> _Myt</span><span style=3D"color:#660">&amp;&amp;</span><span style=3D"co=
lor:#000"> other</span><span style=3D"color:#660">)</span><span style=3D"co=
lor:#000"> </span><span style=3D"color:#660">{</span><span style=3D"color:#=
000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><spa=
n style=3D"color:#008">this</span></div></code></div></div>...</blockquote>=
</div></div></blockquote></blockquote></div></div></div></blockquote></div>=
</div></blockquote></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&quot; 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_6530_624566870.1436976949861--
------=_Part_6529_170840057.1436976949860--

.


Author: Edward Catmur <ed@catmur.co.uk>
Date: Wed, 15 Jul 2015 09:21:44 -0700 (PDT)
Raw View
------=_Part_2695_1330950022.1436977304155
Content-Type: multipart/alternative;
 boundary="----=_Part_2696_564250667.1436977304156"

------=_Part_2696_564250667.1436977304156
Content-Type: text/plain; charset=UTF-8

Why is that necessary? If your wrapper class has a conversion function to
the underlying type then it'll work with the default or user-provided
hasher transparently, by the usual overload resolution rules.

On Wednesday, 15 July 2015 17:15:49 UTC+1, Omer Rosler wrote:
>
> I think you misunderstood me :)
> I'm not talking about examples, I'm talking about the fact that the hasher
> here depends only on the comparator, so defining it seems redundant .
> Basically I'm looking for a general hasher of this wrapper, based on a
> comparator and the hasher of the underlying type. Something like:
> template<class Key,class Comp, class Hahser = std::hash<Key> >
> struct hash<const_wrapper<Key, Comp, Hasher> > {
>      size_t operator()(const const_wrapper<Key, Comp, Hasher>&) {/*some
> magic...*/}
> }
> (Not specializing this template, but having a general definition)
> And let the user define the comparator and the hasher of the underlying
> type only, as it is today.
> I don't want the fact that the objects stored in the map can be changed to
> make the user write a diffrent code.
> If something like this is possible I think it's worthy as a library
> extension.
>
> On Wednesday, July 15, 2015 at 6:59:02 PM UTC+3, Edward Catmur wrote:
>>
>> In the cases where it's legitimate to modify the key (generally a record
>> where only some fields participate in the key identity) one has to provide
>> a hasher and comparator expressing that restricted identity concept; that's
>> what my example was intended to model. There's no need to provide another
>> hasher or comparator.
>>
>> Perhaps I misunderstood your intent; could you provide a simple use case
>> like I did above?
>>
>> On Wednesday, 15 July 2015 16:49:50 UTC+1, Omer Rosler wrote:
>>>
>>> Of course I want to hash on the underlying type, but I don't want to
>>> create another function to do it for me like in your example. In the
>>> original suggstion the function simply called a hasher once (on the real
>>> object), saved the value and returned it as if the object is const (this
>>> all done in a single template and not comparator specific like in your
>>> example), but this takes more momery (sizeof(size_t) per object).
>>> I see the problem in using static hashers, maybe a few static functions
>>> that can change the state of the hasher.
>>> Well, if this limited-access class is not that common than this
>>> discussion is pointless anyway...
>>>
>>> On Wednesday, July 15, 2015 at 4:50:27 PM UTC+3, Edward Catmur wrote:
>>>>
>>>> On Wednesday, 15 July 2015 13:44:04 UTC+1, Omer Rosler wrote:
>>>>>
>>>>> First, Thanks for the feedback.
>>>>> The reason I used the default value of the Comparator to be
>>>>> std::equal_to is because I wanted this class to be a stand-alone,
>>>>> regardless of containers; containers will use it with !comp(lhs, rhs)
>>>>> && !comp(rhs, lhs) instead of this default value as you mentionted.
>>>>> I did not know about the mutable keyword, this simplifies things alot,
>>>>> so thank you for that.
>>>>> About the unordered containers: I don't want to define a new hash
>>>>> function every time I use an unordered container with this type, although I
>>>>> can't see a solution that doesn't take more memory (or any possible way of
>>>>> making a template hasher that performs a hash on a representative for
>>>>> general type and general comparator).
>>>>>
>>>>
>>>> Why not just use the hash on the underlying type?
>>>>
>>>>
>>>>> If a limited access wrapper like this is a common nescessity (beyond
>>>>> mutable keys in associative containers) then maybe it is worth standarizing
>>>>> on it's own.
>>>>> If so, the comparator needs not to come from a container, so using a
>>>>> static member is probably the solution.
>>>>>
>>>>
>>>> The problem there is that hashers can have state (e.g. a function
>>>> pointer or a type-erased function wrapper), so a static member won't work.
>>>> I can't think of any use other than associative containers, so you might as
>>>> well use the container's comparator and hasher.
>>>>
>>>>
>>>>> So, is this limited access wrapper worth standarizing?
>>>>>
>>>>> On Tuesday, July 14, 2015 at 11:23:45 PM UTC+3, Omer Rosler wrote:
>>>>>>
>>>>>> This is the first time I share my ideas about C++, so don't be too
>>>>>> harsh :)
>>>>>> This post is an attempt to partially solve the problem of key
>>>>>> replacement  in (unordered) associative containers such as
>>>>>> (unordered_)(multi)map, (unordered_)(multi)set* when the object
>>>>>> doesn't move inside the container after replacement and the value *up
>>>>>> to the comparator* is the same.
>>>>>> *The braces () mean optiopnal.
>>>>>> Note that in ordered containers if the value doesn't change (up to
>>>>>> the comparator) so does the position of the object; in unordered this gets
>>>>>> trickier, but we'll get to that later.
>>>>>> My aproach is to create an intermediate class that provides a
>>>>>> const-like access to a object but allows changing it if a comparator yields
>>>>>> true (so the complexity of the assignment operator is the maximum of the
>>>>>> complexity of the object type's assignemnt operator, and the comparator's
>>>>>> complexity).
>>>>>> In case of setting a diffrent value this class can either throw some
>>>>>> exception or simply do nothing (up for debate).
>>>>>> By using this class inside the underlying RB tree as the value type
>>>>>> (instead of a simple const type) it will allow iterators to change the
>>>>>> value of the key they hold by calling the wrapper class's assignemnt
>>>>>> iterator.
>>>>>> I haven't decided whether it's smart to make this class public and
>>>>>> change the containers' value type (meaning: big diffrence from older
>>>>>> versions for all 8 containers, although the conversion operator makes old
>>>>>> code work all the same), or simply make it private and convert to
>>>>>> container's value type inside the iterators which will now have setter
>>>>>> functions.
>>>>>> The second option has major downsides: The current iterators
>>>>>> interface needs to be changed, instead of holding const key as a public
>>>>>> member (like it does now), it will hold this wrapper class as a
>>>>>> private/protected member, and accessing it must be done using a function
>>>>>> call to a getter that calls a conversion operator (so access is using
>>>>>> funtion calls only, instead of accessing a public member):
>>>>>> template<class Key_type, Compare Comparator = std::equal_to<Key_type>
>>>>>> >
>>>>>> struct iterator {
>>>>>>         //other code...
>>>>>>         const Key_type& key() const { //getter
>>>>>>                 return m_value; //call conversion operator
>>>>>>         }
>>>>>>         const Key_type& key(const Key_type&x) { //setter
>>>>>>                 return m_value = x; //call copy assignment operator
>>>>>> of wrapper class
>>>>>>         }
>>>>>> private:
>>>>>>         const_to_comparison<Key_type, Comparator> m_value
>>>>>> };
>>>>>>
>>>>>> (The name 'key' isn't the real function name, for map iterator it
>>>>>> will be 'first', and for the set iterator it will be operator* for getter
>>>>>> and set (maybe not a good name in this case) for setter)
>>>>>> It is possible to be made compatible with other versions but will
>>>>>> make the container to hold another public member for the converted type
>>>>>> which takes twice the memory it used to.
>>>>>> So maybe the first option where this wrapper class is public is
>>>>>> better (at least in my opinion).
>>>>>> Maybe there are other places this const-like access can be used.
>>>>>> Well, the wrapper looks basically like this:
>>>>>>
>>>>>> namespace std {
>>>>>> template<class _Kty, Compare _Pr = std::equal_to<_Kty> >
>>>>>> class const_to_comparison {
>>>>>>         typedef const_to_comparison<_Kty, _Pr> _Myt;
>>>>>>         typedef _Kty key_type;
>>>>>>         typedef _Pr key_compare;
>>>>>>         static const key_compare comp = _Pr();
>>>>>> public:
>>>>>>         constexpr const_to_comparison() = default;
>>>>>>         constexpr const_to_comparison(const key_type& key) : m_value(
>>>>>> key) {}
>>>>>>         constexpr const_to_comparison(const _Myt& other) : m_value(
>>>>>> other.key) {}
>>>>>>         constexpr const_to_comparison(const _Myt&& other) : m_value(
>>>>>> other.key) {}
>>>>>>                 _Myt& operator=(const_to_comparison&& other) {
>>>>>>                 if (!comp(m_value, other.m_value))
>>>>>>                          std::bad_exception("can't change this value"
>>>>>> ); //colud be any other exception or simply do nothing
>>>>>>                 m_value = other.m_value; //calling move operator=
>>>>>>         }
>>>>>>         _Myt& operator=(const_to_comparison& other) {
>>>>>>                 if (!comp(m_value, other.m_value))
>>>>>>                          std::bad_exception("can't change this value"
>>>>>> ); //colud be any other exception or simply do nothing
>>>>>>                 m_value = other.m_value; //calling copy operator=
>>>>>>         }
>>>>>>         operator const _Kty&() { //for casting to the container's
>>>>>> value_type inside the iterator
>>>>>>                 return m_value;
>>>>>>         }
>>>>>>         ~const_to_comparison() = default;
>>>>>> private:
>>>>>>         key_type m_value;
>>>>>> };
>>>>>> }
>>>>>>
>>>>>> For unordered containers this obviously wouldn't work since the hash
>>>>>> value would change every time the key changes and so will the position in
>>>>>> the container, and this whole mechanism will fail.
>>>>>> Therefore the hash value must remain constant after equal key
>>>>>> replacement, so I tried to solve it the simplest way I could think of (I
>>>>>> don't really like this solution so feel free to rip it to shreds):
>>>>>> Save the hash value of the original object in another field and
>>>>>> overload std::hash of this wrapper class to return this field.
>>>>>> Something like this:
>>>>>>
>>>>>> namespace std {
>>>>>> template<class _Kty, Compare _Pr = std::equal_to<_Kty>, Hash _Hasher
>>>>>> = std::hash<_Kty> >
>>>>>> class const_to_comparison_and_hash_value : public
>>>>>> const_to_comparison < _Kty, _Pr > {
>>>>>>         typedef const_to_comparison< _Kty, _Pr> _Mybase;
>>>>>>         typedef const_to_comparison_and_hash_value<_Kty, _Pr, _Hasher
>>>>>> > _Myt;
>>>>>>         typedef _Kty key_type;
>>>>>>         typedef _Pr key_compare;
>>>>>>         typedef _Hasher key_hash;
>>>>>>         static const key_hash hash = _Hasher();
>>>>>> public:
>>>>>>         constexpr const_to_comparison_and_hash_value() : _Mybase() {}
>>>>>>         constexpr const_to_comparison_and_hash_value(const key_type&
>>>>>> other) : _Mybase(other) {}
>>>>>>         constexpr const_to_comparison_and_hash_value(const _Mybase&
>>>>>> other) : _Mybase(other) {}
>>>>>>         constexpr const_to_comparison_and_hash_value(const _Myt&
>>>>>> other) : _Mybase(other) {}
>>>>>>         constexpr const_to_comparison_and_hash_value(const _Myt&&
>>>>>> other) : _Mybase(other) {}
>>>>>>         _Myt& operator=(const _Myt& other) {
>>>>>>                 this->_Mybase::operator=((const _Mybase&)other);
>>>>>>         }
>>>>>>         _Myt& operator=(const _Myt&& other) {
>>>>>>                this
>>>>>> ...
>>>>>
>>>>>

--

---
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_2696_564250667.1436977304156
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Why is that necessary? If your wrapper class has a convers=
ion function to the underlying type then it&#39;ll work with the default or=
 user-provided hasher transparently, by the usual overload resolution rules=
..<br><br>On Wednesday, 15 July 2015 17:15:49 UTC+1, Omer Rosler  wrote:<blo=
ckquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-=
left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">I think you misun=
derstood me :)<div>I&#39;m not talking about examples, I&#39;m talking abou=
t the fact that the hasher here depends only on the comparator, so defining=
 it seems redundant . Basically I&#39;m looking for a general hasher of thi=
s wrapper, based on a comparator and the hasher of the underlying type. Som=
ething like:</div><div><div style=3D"border:1px solid rgb(187,187,187);word=
-wrap:break-word;background-color:rgb(250,250,250)"><code><div><font color=
=3D"#660066"><span style=3D"color:#008">template</span><span style=3D"color=
:#660">&lt;</span><span style=3D"color:#008">class</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#606">Key</span><span style=3D"color:=
#660">,</span><span style=3D"color:#008">class</span><span style=3D"color:#=
000"> </span><span style=3D"color:#606">Comp</span><span style=3D"color:#66=
0">,</span><span style=3D"color:#000"> </span><span style=3D"color:#008">cl=
ass</span><span style=3D"color:#000"> </span><span style=3D"color:#606">Hah=
ser</span><span style=3D"color:#000"> </span><span style=3D"color:#660">=3D=
</span><span style=3D"color:#000"> std</span><span style=3D"color:#660">::<=
/span><span style=3D"color:#000">hash</span><span style=3D"color:#660">&lt;=
</span><span style=3D"color:#606">Key</span><span style=3D"color:#660">&gt;=
</span><span style=3D"color:#000"> </span><span style=3D"color:#660">&gt;</=
span><span style=3D"color:#000"><br></span><span style=3D"color:#008">struc=
t</span><span style=3D"color:#000"> hash</span><span style=3D"color:#660">&=
lt;</span><span style=3D"color:#000">const_wrapper</span><span style=3D"col=
or:#660">&lt;</span><span style=3D"color:#606">Key</span><span style=3D"col=
or:#660">,</span><span style=3D"color:#000"> </span><span style=3D"color:#6=
06">Comp</span><span style=3D"color:#660">,</span><span style=3D"color:#000=
"> </span><span style=3D"color:#606">Hasher</span><span style=3D"color:#660=
">&gt;</span><span style=3D"color:#000"> </span><span style=3D"color:#660">=
&gt;</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{<=
/span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0size_t </span><spa=
n style=3D"color:#008">operator</span><span style=3D"color:#660">()(</span>=
<span style=3D"color:#008">const</span><span style=3D"color:#000"> const_wr=
apper</span><span style=3D"color:#660">&lt;</span><span style=3D"color:#606=
">Key</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> =
</span><span style=3D"color:#606">Comp</span><span style=3D"color:#660">,</=
span><span style=3D"color:#000"> </span><span style=3D"color:#606">Hasher</=
span><span style=3D"color:#660">&gt;&amp;)</span><span style=3D"color:#000"=
> </span><span style=3D"color:#660">{</span><span style=3D"color:#800">/*so=
me magic...*/</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></span></font></div></code></div>(Not specializing this template, =
but having a general definition)</div><div>And let the user define the comp=
arator and the hasher of the underlying type only, as it is today.</div><di=
v>I don&#39;t want the fact that the objects stored in the map can be chang=
ed to make the user write a diffrent code.<br>If something like this is pos=
sible I think it&#39;s worthy as a library extension.<br><br>On Wednesday, =
July 15, 2015 at 6:59:02 PM UTC+3, Edward Catmur wrote:<blockquote class=3D=
"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc soli=
d;padding-left:1ex"><div dir=3D"ltr">In the cases where it&#39;s legitimate=
 to modify the key (generally a record where only some fields participate i=
n the key identity) one has to provide a hasher and comparator expressing t=
hat restricted identity concept; that&#39;s what my example was intended to=
 model. There&#39;s no need to provide another hasher or comparator.<div><b=
r></div><div>Perhaps I misunderstood your intent; could you provide a simpl=
e use case like I did above?<br><br>On Wednesday, 15 July 2015 16:49:50 UTC=
+1, Omer Rosler  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">Of course I want to hash on the underlying type, but I don&#39;t want =
to create another function to do it for me like in your example. In the ori=
ginal suggstion the function simply called a hasher once (on the real objec=
t), saved the value and returned it as if the object is const (this all don=
e in a single template and not comparator specific like in your example), b=
ut this takes more momery (sizeof(size_t) per object).<div>I see the proble=
m in using static hashers, maybe a few static functions that can change the=
 state of the hasher.</div><div>Well, if this limited-access class is not t=
hat common than this discussion is pointless anyway...</div><div><br><div>O=
n Wednesday, July 15, 2015 at 4:50:27 PM UTC+3, Edward Catmur wrote:<blockq=
uote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:=
1px #ccc solid;padding-left:1ex">On Wednesday, 15 July 2015 13:44:04 UTC+1,=
 Omer Rosler  wrote:<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=
">First, Thanks for the feedback.<div>The reason I used the default value o=
f the Comparator to be std::equal_to is because I wanted this class to be a=
 stand-alone, regardless of containers; containers will use it with=C2=A0<s=
pan style=3D"font-family:&#39;courier new&#39;,monospace">!comp(lhs, rhs) &=
amp;&amp; !comp(rhs, lhs)</span>=C2=A0instead of this default value as you =
mentionted.</div><div>I did not know about the mutable keyword, this simpli=
fies things alot, so thank you for that.</div><div>About the unordered cont=
ainers: I don&#39;t want to define a new hash function every time I use an =
unordered container with this type, although I can&#39;t see a solution tha=
t doesn&#39;t take more memory (or any possible way of making a template ha=
sher that performs a hash on a representative for general type and general =
comparator).</div></div></blockquote><div><br></div><div>Why not just use t=
he hash on the underlying type?</div><div>=C2=A0</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>If a limited access wrapper like t=
his is a common nescessity (beyond mutable keys in associative containers) =
then maybe it is worth standarizing on it&#39;s own.</div><div>If so, the c=
omparator needs not to come from a container, so using a static member is p=
robably the solution.</div></div></blockquote><div><br></div><div>The probl=
em there is that hashers can have state (e.g. a function pointer or a type-=
erased function wrapper), so a static member won&#39;t work. I can&#39;t th=
ink of any use other than associative containers, so you might as well use =
the container&#39;s comparator and hasher.</div><div>=C2=A0</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"><div>So, is this limited acc=
ess wrapper worth standarizing?<br><br>On Tuesday, July 14, 2015 at 11:23:4=
5 PM UTC+3, Omer Rosler wrote:<blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div =
dir=3D"ltr"><div>This is the first time I share my ideas about C++, so don&=
#39;t be too harsh :)<br></div><div>This post is an attempt to partially so=
lve the problem of key replacement =C2=A0in (unordered) associative contain=
ers such as</div><div>(unordered_)(multi)map, (unordered_)(multi)set* when =
the object doesn&#39;t move inside the container after replacement and the =
value <b>up to the comparator</b> is the same.</div><div>*The braces () mea=
n optiopnal.</div><div>Note that in ordered containers if the value doesn&#=
39;t change (up to the comparator) so does the position of the object; in u=
nordered this gets trickier, but we&#39;ll get to that later.</div><div>My =
aproach is to create an intermediate class that provides a const-like acces=
s to a object but allows changing it if a comparator yields true (so the co=
mplexity of the assignment operator is the maximum of the complexity of the=
 object type&#39;s assignemnt operator, and the comparator&#39;s complexity=
).</div><div>In case of setting a diffrent value this class can either thro=
w some exception or simply do nothing (up for debate).</div><div>By using t=
his class inside the underlying RB tree as the value type (instead of a sim=
ple const type) it will allow iterators to change the value of the key they=
 hold by calling the wrapper class&#39;s assignemnt iterator.</div><div>I h=
aven&#39;t decided whether it&#39;s smart to make this class public and cha=
nge the containers&#39; value type (meaning: big diffrence from older versi=
ons for all 8 containers, although the conversion operator makes old code w=
ork all the same), or simply make it private and convert to container&#39;s=
 value type inside the iterators which will now have setter functions.</div=
><div>The second option has major downsides: The current iterators interfac=
e needs to be changed, instead of holding const key as a public member (lik=
e it does now), it will hold this wrapper class as a private/protected memb=
er, and accessing it must be done using a function call to a getter that ca=
lls a conversion operator (so access is using funtion calls only, instead o=
f accessing a public member):</div><div><div style=3D"border:1px solid rgb(=
187,187,187);word-wrap:break-word;background-color:rgb(250,250,250)"><code>=
<div><span style=3D"color:#008">template</span><span style=3D"color:#660">&=
lt;</span><span style=3D"color:#008">class</span><span style=3D"color:#000"=
> </span><span style=3D"color:#606">Key_type</span><span style=3D"color:#66=
0">,</span><span style=3D"color:#000"> </span><span style=3D"color:#606">Co=
mpare</span><span style=3D"color:#000"> </span><span style=3D"color:#606">C=
omparator</span><span style=3D"color:#000"> </span><span style=3D"color:#66=
0">=3D</span><span style=3D"color:#000"> std</span><span style=3D"color:#66=
0">::</span><span style=3D"color:#000">equal_to</span><span style=3D"color:=
#660">&lt;</span><span style=3D"color:#606">Key_type</span><span style=3D"c=
olor:#660">&gt;</span><span style=3D"color:#000"> </span><span style=3D"col=
or:#660">&gt;</span><span style=3D"color:#000"><br></span><span style=3D"co=
lor:#008">struct</span><span style=3D"color:#000"> iterator </span><span st=
yle=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 </span><span style=3D"color:#800">//other code...</span><span st=
yle=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"co=
lor:#008">const</span><span style=3D"color:#000"> </span><span style=3D"col=
or:#606">Key_type</span><span style=3D"color:#660">&amp;</span><span style=
=3D"color:#000"> key</span><span style=3D"color:#660">()</span><span style=
=3D"color:#000"> </span><span style=3D"color:#008">const</span><font color=
=3D"#666600"><span style=3D"color:#000"> </span><span style=3D"color:#660">=
{</span></font><span style=3D"color:#000"> </span><span style=3D"color:#800=
">//getter</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0=
 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span=
><span style=3D"color:#000"> m_value</span><span style=3D"color:#660">;</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#800">//</span><=
font color=3D"#000000"><span style=3D"color:#800">call conversion operator<=
/span><span style=3D"color:#000"><br></span></font><span style=3D"color:#00=
0">=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><s=
pan style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=
=3D"color:#008">const</span><span style=3D"color:#000"> </span><span style=
=3D"color:#606">Key_type</span><span style=3D"color:#660">&amp;</span><span=
 style=3D"color:#000"> key</span><span style=3D"color:#660">(</span><span s=
tyle=3D"color:#008">const</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#606">Key_type</span><span style=3D"color:#660">&amp;</span><s=
pan style=3D"color:#000">x</span><span style=3D"color:#660">)</span><span s=
tyle=3D"color:#000"> </span><span style=3D"color:#660">{</span><span style=
=3D"color:#000"> </span><span style=3D"color:#800">//setter</span><span sty=
le=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 </span><span style=3D"color:#008">return</span><span style=3D"color:#00=
0"> m_value </span><span style=3D"color:#660">=3D</span><span style=3D"colo=
r:#000"> x</span><span style=3D"color:#660">;</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#800">//call copy assignment operator of w=
rapper class</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 </span><span style=3D"color:#660">}</span><span style=3D"color:#000"><b=
r></span><span style=3D"color:#008">private</span><span style=3D"color:#660=
">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 const_=
to_comparison</span><span style=3D"color:#660">&lt;</span><span style=3D"co=
lor:#606">Key_type</span><span style=3D"color:#660">,</span><span style=3D"=
color:#000"> </span><span style=3D"color:#606">Comparator</span><span style=
=3D"color:#660">&gt;</span><span style=3D"color:#000"> m_value<br></span><s=
pan style=3D"color:#660">};</span><font color=3D"#666600"></font></div></co=
de></div></div><div><br></div><div>(The name &#39;key&#39; isn&#39;t the re=
al function name, for map iterator it will be &#39;first&#39;, and for the =
set iterator it will be operator* for getter and set (maybe not a good name=
 in this case) for setter)</div><div>It is possible to be made compatible w=
ith other versions but will make the container to hold another public membe=
r for the converted type which takes twice the memory it used to.</div><div=
>So maybe the first option where this wrapper class is public is better (at=
 least in my opinion).</div><div>Maybe there are other places this const-li=
ke access can be used.</div><div>Well, the wrapper looks basically like thi=
s:</div><div><br></div><div style=3D"border:1px solid rgb(187,187,187);word=
-wrap:break-word;background-color:rgb(250,250,250)"><code><div><span style=
=3D"color:#008">namespace</span><span style=3D"color:#000"> std </span><spa=
n style=3D"color:#660">{</span><span style=3D"color:#000"><br></span><span =
style=3D"color:#008">template</span><span style=3D"color:#660">&lt;</span><=
span style=3D"color:#008">class</span><span style=3D"color:#000"> _Kty</spa=
n><span style=3D"color:#660">,</span><span style=3D"color:#000"> </span><sp=
an style=3D"color:#606">Compare</span><span style=3D"color:#000"> _Pr </spa=
n><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> std</spa=
n><span style=3D"color:#660">::</span><span style=3D"color:#000">equal_to</=
span><span style=3D"color:#660">&lt;</span><span style=3D"color:#000">_Kty<=
/span><span style=3D"color:#660">&gt;</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#660">&gt;</span><span style=3D"color:#000"><br></=
span><span style=3D"color:#008">class</span><span style=3D"color:#000"> con=
st_to_comparison </span><span style=3D"color:#660">{</span><span style=3D"c=
olor:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008=
">typedef</span><span style=3D"color:#000"> const_to_comparison</span><span=
 style=3D"color:#660">&lt;</span><span style=3D"color:#000">_Kty</span><spa=
n style=3D"color:#660">,</span><span style=3D"color:#000"> _Pr</span><span =
style=3D"color:#660">&gt;</span><span style=3D"color:#000"> _Myt</span><spa=
n style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0=
 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typedef</span><span style=
=3D"color:#000"> _Kty key_type</span><span style=3D"color:#660">;</span><sp=
an style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=
=3D"color:#008">typedef</span><span style=3D"color:#000"> _Pr key_compare</=
span><span style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">static</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#008">const</span><spa=
n style=3D"color:#000"> key_compare comp </span><span style=3D"color:#660">=
=3D</span><span style=3D"color:#000"> _Pr</span><span style=3D"color:#660">=
();</span><span style=3D"color:#000"><br></span><span style=3D"color:#008">=
public</span><span style=3D"color:#660">:</span><span style=3D"color:#000">=
<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr=
</span><span style=3D"color:#000"> const_to_comparison</span><span style=3D=
"color:#660">()</span><span style=3D"color:#000"> </span><span style=3D"col=
or:#660">=3D</span><span style=3D"color:#000"> </span><span style=3D"color:=
#008">default</span><span style=3D"color:#660">;</span><span style=3D"color=
:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">co=
nstexpr</span><span style=3D"color:#000"> const_to_comparison</span><span s=
tyle=3D"color:#660">(</span><span style=3D"color:#008">const</span><span st=
yle=3D"color:#000"> key_type</span><span style=3D"color:#660">&amp;</span><=
span style=3D"color:#000"> key</span><span style=3D"color:#660">)</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#660">:</span><span st=
yle=3D"color:#000"> m_value</span><span style=3D"color:#660">(</span><span =
style=3D"color:#000">key</span><span style=3D"color:#660">)</span><span sty=
le=3D"color:#000"> </span><span style=3D"color:#660">{}</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color=
:#008">constexpr</span><span style=3D"color:#000"> const_to_comparison</spa=
n><span style=3D"color:#660">(</span><span style=3D"color:#008">const</span=
><span style=3D"color:#000"> _Myt</span><span style=3D"color:#660">&amp;</s=
pan><span style=3D"color:#000"> other</span><span style=3D"color:#660">)</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#660">:</span><=
span style=3D"color:#000"> m_value</span><span style=3D"color:#660">(</span=
><span style=3D"color:#000">other</span><span style=3D"color:#660">.</span>=
<span style=3D"color:#000">key</span><span style=3D"color:#660">)</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#660">{}</span><span s=
tyle=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"c=
olor:#008">constexpr</span><span style=3D"color:#000"> const_to_comparison<=
/span><span style=3D"color:#660">(</span><span style=3D"color:#008">const</=
span><span style=3D"color:#000"> _Myt</span><span style=3D"color:#660">&amp=
;&amp;</span><span style=3D"color:#000"> other</span><span style=3D"color:#=
660">)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">=
:</span><span style=3D"color:#000"> m_value</span><span style=3D"color:#660=
">(</span><span style=3D"color:#000">other</span><span style=3D"color:#660"=
>.</span><span style=3D"color:#000">key</span><span style=3D"color:#660">)<=
/span><span style=3D"color:#000"> </span><span style=3D"color:#660">{}</spa=
n><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 _Myt</span><span style=3D"color:#660">&amp;</span><span style=
=3D"color:#000"> </span><span style=3D"color:#008">operator</span><span sty=
le=3D"color:#660">=3D(</span><span style=3D"color:#000">const_to_comparison=
</span><span style=3D"color:#660">&amp;&amp;</span><span style=3D"color:#00=
0"> other</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>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span styl=
e=3D"color:#008">if</span><span style=3D"color:#000"> </span><span style=3D=
"color:#660">(!</span><span style=3D"color:#000">comp</span><span style=3D"=
color:#660">(</span><span style=3D"color:#000">m_value</span><span style=3D=
"color:#660">,</span><span style=3D"color:#000"> other</span><span style=3D=
"color:#660">.</span><span style=3D"color:#000">m_value</span><span style=
=3D"color:#660">))</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0st=
d</span><span style=3D"color:#660">::</span><span style=3D"color:#000">bad_=
exception</span><span style=3D"color:#660">(</span><span style=3D"color:#08=
0">&quot;can&#39;t change this value&quot;</span><span style=3D"color:#660"=
>);</span><span style=3D"color:#000"> </span><span style=3D"color:#800">//c=
olud be any other exception or simply do nothing</span><span style=3D"color=
:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 m_value =
</span><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> oth=
er</span><span style=3D"color:#660">.</span><span style=3D"color:#000">m_va=
lue</span><span style=3D"color:#660">;</span><span style=3D"color:#000"> </=
span><span style=3D"color:#800">//calling move operator=3D</span><span styl=
e=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"colo=
r:#660">}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
_Myt</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#000=
"> </span><span style=3D"color:#008">operator</span><span style=3D"color:#6=
60">=3D(</span><span style=3D"color:#000">const_to_comparison</span><span s=
tyle=3D"color:#660">&amp;</span><span style=3D"color:#000"> other</span><sp=
an style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">if=
</span><span style=3D"color:#000"> </span><span style=3D"color:#660">(!</sp=
an><span style=3D"color:#000">comp</span><span style=3D"color:#660">(</span=
><span style=3D"color:#000">m_value</span><span style=3D"color:#660">,</spa=
n><span style=3D"color:#000"> other</span><span style=3D"color:#660">.</spa=
n><span style=3D"color:#000">m_value</span><span style=3D"color:#660">))</s=
pan><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0std</span><span style=
=3D"color:#660">::</span><span style=3D"color:#000">bad_exception</span><sp=
an style=3D"color:#660">(</span><span style=3D"color:#080">&quot;can&#39;t =
change this value&quot;</span><span style=3D"color:#660">);</span><span sty=
le=3D"color:#000"> </span><span style=3D"color:#800">//colud be any other e=
xception or simply do nothing</span><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 m_value </span><span style=
=3D"color:#660">=3D</span><span style=3D"color:#000"> other</span><span sty=
le=3D"color:#660">.</span><span style=3D"color:#000">m_value</span><span st=
yle=3D"color:#660">;</span><span style=3D"color:#000"> </span><span style=
=3D"color:#800">//calling copy operator=3D</span><span style=3D"color:#000"=
><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span>=
<span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span sty=
le=3D"color:#008">operator</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#008">const</span><span style=3D"color:#000"> _Kty</span><spa=
n style=3D"color:#660">&amp;()</span><span style=3D"color:#000"> </span><sp=
an style=3D"color:#660">{</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#800">//for casting to the container&#39;s value_type inside t=
he iterator</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</s=
pan><span style=3D"color:#000"> m_value</span><span style=3D"color:#660">;<=
/span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><sp=
an style=3D"color:#660">}</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660">~</span><span style=3D"=
color:#000">const_to_comparison</span><span style=3D"color:#660">()</span><=
span style=3D"color:#000"> </span><span style=3D"color:#660">=3D</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#008">default</span><sp=
an style=3D"color:#660">;</span><span style=3D"color:#000"><br></span><span=
 style=3D"color:#008">private</span><span style=3D"color:#660">:</span><spa=
n style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 key_type m_value</sp=
an><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></span>=
<span style=3D"color:#660">}</span></div></code></div><div style=3D"font-fa=
mily:monospace;background-color:rgb(250,250,250)"><br></div><div>For unorde=
red containers this obviously wouldn&#39;t work since the hash value would =
change every time the key changes and so will the position in the container=
, and this whole mechanism will fail.</div><div>Therefore the hash value mu=
st remain constant after equal key replacement, so I tried to solve it the =
simplest way I could think of (I don&#39;t really like this solution so fee=
l free to rip it to shreds):</div><div>Save the hash value of the original =
object in another field and overload std::hash of this wrapper class to ret=
urn this field.</div><div>Something like this:</div><div style=3D"border:1p=
x solid rgb(187,187,187);word-wrap:break-word;background-color:rgb(250,250,=
250)"><code><div><span style=3D"color:#000"><br></span><span style=3D"color=
:#008">namespace</span><span style=3D"color:#000"> std </span><span style=
=3D"color:#660">{</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#008">template</span><span style=3D"color:#660">&lt;</span><span =
style=3D"color:#008">class</span><span style=3D"color:#000"> _Kty</span><sp=
an style=3D"color:#660">,</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#606">Compare</span><span style=3D"color:#000"> _Pr </span><sp=
an style=3D"color:#660">=3D</span><span style=3D"color:#000"> std</span><sp=
an style=3D"color:#660">::</span><span style=3D"color:#000">equal_to</span>=
<span style=3D"color:#660">&lt;</span><span style=3D"color:#000">_Kty</span=
><span style=3D"color:#660">&gt;,</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#606">Hash</span><span style=3D"color:#000"> _Hasher <=
/span><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> std<=
/span><span style=3D"color:#660">::</span><span style=3D"color:#000">hash</=
span><span style=3D"color:#660">&lt;</span><span style=3D"color:#000">_Kty<=
/span><span style=3D"color:#660">&gt;</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#660">&gt;</span><span style=3D"color:#000"><br></=
span><span style=3D"color:#008">class</span><span style=3D"color:#000"> con=
st_to_comparison_and_hash_value </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"> const_to_comparison </span><span style=3D"color:=
#660">&lt;</span><span style=3D"color:#000"> _Kty</span><span style=3D"colo=
r:#660">,</span><span style=3D"color:#000"> _Pr </span><span style=3D"color=
:#660">&gt;</span><span style=3D"color:#000"> </span><span style=3D"color:#=
660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </s=
pan><span style=3D"color:#008">typedef</span><span style=3D"color:#000"> co=
nst_to_comparison</span><span style=3D"color:#660">&lt;</span><span style=
=3D"color:#000"> _Kty</span><span style=3D"color:#660">,</span><span style=
=3D"color:#000"> _Pr</span><span style=3D"color:#660">&gt;</span><span styl=
e=3D"color:#000"> _Mybase</span><span style=3D"color:#660">;</span><span st=
yle=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"co=
lor:#008">typedef</span><span style=3D"color:#000"> const_to_comparison_and=
_hash_value</span><span style=3D"color:#660">&lt;</span><span style=3D"colo=
r:#000">_Kty</span><span style=3D"color:#660">,</span><span style=3D"color:=
#000"> _Pr</span><span style=3D"color:#660">,</span><span style=3D"color:#0=
00"> _Hasher</span><span style=3D"color:#660">&gt;</span><span style=3D"col=
or:#000"> _Myt</span><span style=3D"color:#660">;</span><span style=3D"colo=
r:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">t=
ypedef</span><span style=3D"color:#000"> _Kty key_type</span><span style=3D=
"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color:#008">typedef</span><span style=3D"color=
:#000"> _Pr key_compare</span><span style=3D"color:#660">;</span><span styl=
e=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"colo=
r:#008">typedef</span><span style=3D"color:#000"> _Hasher key_hash</span><s=
pan style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">static</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#008">const</span><span style=
=3D"color:#000"> key_hash hash </span><span style=3D"color:#660">=3D</span>=
<span style=3D"color:#000"> _Hasher</span><span style=3D"color:#660">();</s=
pan><span style=3D"color:#000"><br></span><span style=3D"color:#008">public=
</span><span style=3D"color:#660">:</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</sp=
an><span style=3D"color:#000"> const_to_comparison_and_hash_value</span><sp=
an style=3D"color:#660">()</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#660">:</span><span style=3D"color:#000"> _Mybase</span><span=
 style=3D"color:#660">()</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#660">{}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</span><span style=3D=
"color:#000"> const_to_comparison_and_hash_value</span><span style=3D"color=
:#660">(</span><span style=3D"color:#008">const</span><span style=3D"color:=
#000"> key_type</span><span style=3D"color:#660">&amp;</span><span style=3D=
"color:#000"> other</span><span style=3D"color:#660">)</span><span style=3D=
"color:#000"> </span><span style=3D"color:#660">:</span><span style=3D"colo=
r:#000"> _Mybase</span><span style=3D"color:#660">(</span><span style=3D"co=
lor:#000">other</span><span style=3D"color:#660">)</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#660">{}</span><span style=3D"color:#=
000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">cons=
texpr</span><span style=3D"color:#000"> const_to_comparison_and_hash_value<=
/span><span style=3D"color:#660">(</span><span style=3D"color:#008">const</=
span><span style=3D"color:#000"> _Mybase</span><span style=3D"color:#660">&=
amp;</span><span style=3D"color:#000"> other</span><span style=3D"color:#66=
0">)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">:<=
/span><span style=3D"color:#000"> _Mybase</span><span style=3D"color:#660">=
(</span><span style=3D"color:#000">other</span><span style=3D"color:#660">)=
</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{}</sp=
an><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span =
style=3D"color:#008">constexpr</span><span style=3D"color:#000"> const_to_c=
omparison_and_hash_value</span><span style=3D"color:#660">(</span><span sty=
le=3D"color:#008">const</span><span style=3D"color:#000"> _Myt</span><span =
style=3D"color:#660">&amp;</span><span style=3D"color:#000"> other</span><s=
pan style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#660">:</span><span style=3D"color:#000"> _Mybase</span><span=
 style=3D"color:#660">(</span><span style=3D"color:#000">other</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>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</span><span style=3D=
"color:#000"> const_to_comparison_and_hash_value</span><span style=3D"color=
:#660">(</span><span style=3D"color:#008">const</span><span style=3D"color:=
#000"> _Myt</span><span style=3D"color:#660">&amp;&amp;</span><span style=
=3D"color:#000"> other</span><span style=3D"color:#660">)</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">:</span><span style=3D"c=
olor:#000"> _Mybase</span><span style=3D"color:#660">(</span><span style=3D=
"color:#000">other</span><span style=3D"color:#660">)</span><span style=3D"=
color:#000"> </span><span style=3D"color:#660">{}</span><span style=3D"colo=
r:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</span><span style=3D"color:#66=
0">&amp;</span><span style=3D"color:#000"> </span><span style=3D"color:#008=
">operator</span><span style=3D"color:#660">=3D(</span><span style=3D"color=
:#008">const</span><span style=3D"color:#000"> _Myt</span><span style=3D"co=
lor:#660">&amp;</span><span style=3D"color:#000"> other</span><span style=
=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">this</spa=
n><span style=3D"color:#660">-&gt;</span><span style=3D"color:#000">_Mybase=
</span><span style=3D"color:#660">::</span><span style=3D"color:#008">opera=
tor</span><span style=3D"color:#660">=3D((</span><span style=3D"color:#008"=
>const</span><span style=3D"color:#000"> _Mybase</span><span style=3D"color=
:#660">&amp;)</span><span style=3D"color:#000">other</span><span style=3D"c=
olor:#660">);</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 </span><span style=3D"color:#660">}</span><span style=3D"color:#000"><b=
r>=C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</span><span style=3D"color:#660">&amp;</=
span><span style=3D"color:#000"> </span><span style=3D"color:#008">operator=
</span><span style=3D"color:#660">=3D(</span><span style=3D"color:#008">con=
st</span><span style=3D"color:#000"> _Myt</span><span style=3D"color:#660">=
&amp;&amp;</span><span style=3D"color:#000"> other</span><span style=3D"col=
or:#660">)</span><span style=3D"color:#000"> </span><span style=3D"color:#6=
60">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#008">this</span></div>=
</code></div></div>...</blockquote></div></div></blockquote></blockquote></=
div></div></div></blockquote></div></div></blockquote></div></div></blockqu=
ote></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; 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_2696_564250667.1436977304156--
------=_Part_2695_1330950022.1436977304155--

.


Author: Omer Rosler <omer.rosler@gmail.com>
Date: Wed, 15 Jul 2015 11:51:31 -0700 (PDT)
Raw View
------=_Part_15_1787304585.1436986291490
Content-Type: multipart/alternative;
 boundary="----=_Part_16_591603680.1436986291496"

------=_Part_16_591603680.1436986291496
Content-Type: text/plain; charset=UTF-8

Because the underlying object inside the underlying class can change and
therefore also it's hash value, so the object will not be in the designated
place in the container by simply using the hash function.
In your example there are two hashers: std::hash<int> and the lambda you
defined taking the hash value of the modulus of the object.
For user defined types 2 hashers must be created, unlike unmutable keys.
What I want to do is to create a template that for every comparator returns
an equal hash value for equal elements (one template).
Your lambda is the solution for the specific comparator you defined, I'm
looking for a general solution.
The only one I can think of is saving the original hash value.

On Tuesday, July 14, 2015 at 11:23:45 PM UTC+3, Omer Rosler wrote:
>
> This is the first time I share my ideas about C++, so don't be too harsh :)
> This post is an attempt to partially solve the problem of key replacement
>  in (unordered) associative containers such as
> (unordered_)(multi)map, (unordered_)(multi)set* when the object doesn't
> move inside the container after replacement and the value *up to the
> comparator* is the same.
> *The braces () mean optiopnal.
> Note that in ordered containers if the value doesn't change (up to the
> comparator) so does the position of the object; in unordered this gets
> trickier, but we'll get to that later.
> My aproach is to create an intermediate class that provides a const-like
> access to a object but allows changing it if a comparator yields true (so
> the complexity of the assignment operator is the maximum of the complexity
> of the object type's assignemnt operator, and the comparator's complexity).
> In case of setting a diffrent value this class can either throw some
> exception or simply do nothing (up for debate).
> By using this class inside the underlying RB tree as the value type
> (instead of a simple const type) it will allow iterators to change the
> value of the key they hold by calling the wrapper class's assignemnt
> iterator.
> I haven't decided whether it's smart to make this class public and change
> the containers' value type (meaning: big diffrence from older versions for
> all 8 containers, although the conversion operator makes old code work all
> the same), or simply make it private and convert to container's value type
> inside the iterators which will now have setter functions.
> The second option has major downsides: The current iterators interface
> needs to be changed, instead of holding const key as a public member (like
> it does now), it will hold this wrapper class as a private/protected
> member, and accessing it must be done using a function call to a getter
> that calls a conversion operator (so access is using funtion calls only,
> instead of accessing a public member):
> template<class Key_type, Compare Comparator = std::equal_to<Key_type> >
> struct iterator {
>         //other code...
>         const Key_type& key() const { //getter
>                 return m_value; //call conversion operator
>         }
>         const Key_type& key(const Key_type&x) { //setter
>                 return m_value = x; //call copy assignment operator of
> wrapper class
>         }
> private:
>         const_to_comparison<Key_type, Comparator> m_value
> };
>
> (The name 'key' isn't the real function name, for map iterator it will be
> 'first', and for the set iterator it will be operator* for getter and set
> (maybe not a good name in this case) for setter)
> It is possible to be made compatible with other versions but will make the
> container to hold another public member for the converted type which takes
> twice the memory it used to.
> So maybe the first option where this wrapper class is public is better (at
> least in my opinion).
> Maybe there are other places this const-like access can be used.
> Well, the wrapper looks basically like this:
>
> namespace std {
> template<class _Kty, Compare _Pr = std::equal_to<_Kty> >
> class const_to_comparison {
>         typedef const_to_comparison<_Kty, _Pr> _Myt;
>         typedef _Kty key_type;
>         typedef _Pr key_compare;
>         static const key_compare comp = _Pr();
> public:
>         constexpr const_to_comparison() = default;
>         constexpr const_to_comparison(const key_type& key) : m_value(key)
> {}
>         constexpr const_to_comparison(const _Myt& other) : m_value(other.
> key) {}
>         constexpr const_to_comparison(const _Myt&& other) : m_value(other.
> key) {}
>                 _Myt& operator=(const_to_comparison&& other) {
>                 if (!comp(m_value, other.m_value))
>                          std::bad_exception("can't change this value"); //colud
> be any other exception or simply do nothing
>                 m_value = other.m_value; //calling move operator=
>         }
>         _Myt& operator=(const_to_comparison& other) {
>                 if (!comp(m_value, other.m_value))
>                          std::bad_exception("can't change this value"); //colud
> be any other exception or simply do nothing
>                 m_value = other.m_value; //calling copy operator=
>         }
>         operator const _Kty&() { //for casting to the container's
> value_type inside the iterator
>                 return m_value;
>         }
>         ~const_to_comparison() = default;
> private:
>         key_type m_value;
> };
> }
>
> For unordered containers this obviously wouldn't work since the hash value
> would change every time the key changes and so will the position in the
> container, and this whole mechanism will fail.
> Therefore the hash value must remain constant after equal key replacement,
> so I tried to solve it the simplest way I could think of (I don't really
> like this solution so feel free to rip it to shreds):
> Save the hash value of the original object in another field and overload
> std::hash of this wrapper class to return this field.
> Something like this:
>
> namespace std {
> template<class _Kty, Compare _Pr = std::equal_to<_Kty>, Hash _Hasher = std
> ::hash<_Kty> >
> class const_to_comparison_and_hash_value : public const_to_comparison <
> _Kty, _Pr > {
>         typedef const_to_comparison< _Kty, _Pr> _Mybase;
>         typedef const_to_comparison_and_hash_value<_Kty, _Pr, _Hasher>
> _Myt;
>         typedef _Kty key_type;
>         typedef _Pr key_compare;
>         typedef _Hasher key_hash;
>         static const key_hash hash = _Hasher();
> public:
>         constexpr const_to_comparison_and_hash_value() : _Mybase() {}
>         constexpr const_to_comparison_and_hash_value(const key_type& other
> ) : _Mybase(other) {}
>         constexpr const_to_comparison_and_hash_value(const _Mybase& other)
> : _Mybase(other) {}
>         constexpr const_to_comparison_and_hash_value(const _Myt& other) :
> _Mybase(other) {}
>         constexpr const_to_comparison_and_hash_value(const _Myt&& other) :
> _Mybase(other) {}
>         _Myt& operator=(const _Myt& other) {
>                 this->_Mybase::operator=((const _Mybase&)other);
>         }
>         _Myt& operator=(const _Myt&& other) {
>                this
> ...

--

---
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_16_591603680.1436986291496
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Because the underlying object inside the underlying class =
can change and therefore also it&#39;s hash value, so the object will not b=
e in the designated place in the container by simply using the hash functio=
n.<div>In your example there are two hashers: std::hash&lt;int&gt; and the =
lambda you defined taking the hash value of the modulus of the object.</div=
><div>For user defined types 2 hashers must be created, unlike unmutable ke=
ys.</div><div>What I want to do is to create a template that for every comp=
arator returns an equal hash value for equal elements (one template).</div>=
<div>Your lambda is the solution for the specific comparator you defined, I=
&#39;m looking for a general solution.</div><div>The only one I can think o=
f is saving the original hash value.</div><div><br>On Tuesday, July 14, 201=
5 at 11:23:45 PM UTC+3, Omer Rosler 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>This is the first time I share my ideas a=
bout C++, so don&#39;t be too harsh :)<br></div><div>This post is an attemp=
t to partially solve the problem of key replacement =C2=A0in (unordered) as=
sociative containers such as</div><div>(unordered_)(multi)map, (unordered_)=
(multi)set* when the object doesn&#39;t move inside the container after rep=
lacement and the value <b>up to the comparator</b> is the same.</div><div>*=
The braces () mean optiopnal.</div><div>Note that in ordered containers if =
the value doesn&#39;t change (up to the comparator) so does the position of=
 the object; in unordered this gets trickier, but we&#39;ll get to that lat=
er.</div><div>My aproach is to create an intermediate class that provides a=
 const-like access to a object but allows changing it if a comparator yield=
s true (so the complexity of the assignment operator is the maximum of the =
complexity of the object type&#39;s assignemnt operator, and the comparator=
&#39;s complexity).</div><div>In case of setting a diffrent value this clas=
s can either throw some exception or simply do nothing (up for debate).</di=
v><div>By using this class inside the underlying RB tree as the value type =
(instead of a simple const type) it will allow iterators to change the valu=
e of the key they hold by calling the wrapper class&#39;s assignemnt iterat=
or.</div><div>I haven&#39;t decided whether it&#39;s smart to make this cla=
ss public and change the containers&#39; value type (meaning: big diffrence=
 from older versions for all 8 containers, although the conversion operator=
 makes old code work all the same), or simply make it private and convert t=
o container&#39;s value type inside the iterators which will now have sette=
r functions.</div><div>The second option has major downsides: The current i=
terators interface needs to be changed, instead of holding const key as a p=
ublic member (like it does now), it will hold this wrapper class as a priva=
te/protected member, and accessing it must be done using a function call to=
 a getter that calls a conversion operator (so access is using funtion call=
s only, instead of accessing a public member):</div><div><div style=3D"bord=
er:1px solid rgb(187,187,187);word-wrap:break-word;background-color:rgb(250=
,250,250)"><code><div><span style=3D"color:#008">template</span><span style=
=3D"color:#660">&lt;</span><span style=3D"color:#008">class</span><span sty=
le=3D"color:#000"> </span><span style=3D"color:#606">Key_type</span><span s=
tyle=3D"color:#660">,</span><span style=3D"color:#000"> </span><span style=
=3D"color:#606">Compare</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#606">Comparator</span><span style=3D"color:#000"> </span><span =
style=3D"color:#660">=3D</span><span style=3D"color:#000"> std</span><span =
style=3D"color:#660">::</span><span style=3D"color:#000">equal_to</span><sp=
an style=3D"color:#660">&lt;</span><span style=3D"color:#606">Key_type</spa=
n><span style=3D"color:#660">&gt;</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#660">&gt;</span><span style=3D"color:#000"><br></span=
><span style=3D"color:#008">struct</span><span style=3D"color:#000"> iterat=
or </span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br=
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#800">//other code=
....</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span=
><span style=3D"color:#008">const</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#606">Key_type</span><span style=3D"color:#660">&amp;<=
/span><span style=3D"color:#000"> key</span><span style=3D"color:#660">()</=
span><span style=3D"color:#000"> </span><span style=3D"color:#008">const</s=
pan><font color=3D"#666600"><span style=3D"color:#000"> </span><span style=
=3D"color:#660">{</span></font><span style=3D"color:#000"> </span><span sty=
le=3D"color:#800">//getter</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#=
008">return</span><span style=3D"color:#000"> m_value</span><span style=3D"=
color:#660">;</span><span style=3D"color:#000"> </span><span style=3D"color=
:#800">//</span><font color=3D"#000000"><span style=3D"color:#800">call con=
version operator</span><span style=3D"color:#000"><br></span></font><span s=
tyle=3D"color:#000">=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color=
:#660">}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 <=
/span><span style=3D"color:#008">const</span><span style=3D"color:#000"> </=
span><span style=3D"color:#606">Key_type</span><span style=3D"color:#660">&=
amp;</span><span style=3D"color:#000"> key</span><span style=3D"color:#660"=
>(</span><span style=3D"color:#008">const</span><span style=3D"color:#000">=
 </span><span style=3D"color:#606">Key_type</span><span style=3D"color:#660=
">&amp;</span><span style=3D"color:#000">x</span><span style=3D"color:#660"=
>)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#800">//setter<=
/span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span><span styl=
e=3D"color:#000"> m_value </span><span style=3D"color:#660">=3D</span><span=
 style=3D"color:#000"> x</span><span style=3D"color:#660">;</span><span sty=
le=3D"color:#000"> </span><span style=3D"color:#800">//call copy assignment=
 operator of wrapper class</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span style=3D"=
color:#000"><br></span><span style=3D"color:#008">private</span><span style=
=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0=
 =C2=A0 const_to_comparison</span><span style=3D"color:#660">&lt;</span><sp=
an style=3D"color:#606">Key_type</span><span style=3D"color:#660">,</span><=
span style=3D"color:#000"> </span><span style=3D"color:#606">Comparator</sp=
an><span style=3D"color:#660">&gt;</span><span style=3D"color:#000"> m_valu=
e<br></span><span style=3D"color:#660">};</span><font color=3D"#666600"></f=
ont></div></code></div></div><div><br></div><div>(The name &#39;key&#39; is=
n&#39;t the real function name, for map iterator it will be &#39;first&#39;=
, and for the set iterator it will be operator* for getter and set (maybe n=
ot a good name in this case) for setter)</div><div>It is possible to be mad=
e compatible with other versions but will make the container to hold anothe=
r public member for the converted type which takes twice the memory it used=
 to.</div><div>So maybe the first option where this wrapper class is public=
 is better (at least in my opinion).</div><div>Maybe there are other places=
 this const-like access can be used.</div><div>Well, the wrapper looks basi=
cally like this:</div><div><br></div><div style=3D"border:1px solid rgb(187=
,187,187);word-wrap:break-word;background-color:rgb(250,250,250)"><code><di=
v><span style=3D"color:#008">namespace</span><span style=3D"color:#000"> st=
d </span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=
</span><span style=3D"color:#008">template</span><span style=3D"color:#660"=
>&lt;</span><span style=3D"color:#008">class</span><span style=3D"color:#00=
0"> _Kty</span><span style=3D"color:#660">,</span><span style=3D"color:#000=
"> </span><span style=3D"color:#606">Compare</span><span style=3D"color:#00=
0"> _Pr </span><span style=3D"color:#660">=3D</span><span style=3D"color:#0=
00"> std</span><span style=3D"color:#660">::</span><span style=3D"color:#00=
0">equal_to</span><span style=3D"color:#660">&lt;</span><span style=3D"colo=
r:#000">_Kty</span><span style=3D"color:#660">&gt;</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#660">&gt;</span><span style=3D"color=
:#000"><br></span><span style=3D"color:#008">class</span><span style=3D"col=
or:#000"> const_to_comparison </span><span style=3D"color:#660">{</span><sp=
an style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=
=3D"color:#008">typedef</span><span style=3D"color:#000"> const_to_comparis=
on</span><span style=3D"color:#660">&lt;</span><span style=3D"color:#000">_=
Kty</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> _P=
r</span><span style=3D"color:#660">&gt;</span><span style=3D"color:#000"> _=
Myt</span><span style=3D"color:#660">;</span><span style=3D"color:#000"><br=
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typedef</spa=
n><span style=3D"color:#000"> _Kty key_type</span><span style=3D"color:#660=
">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span=
><span style=3D"color:#008">typedef</span><span style=3D"color:#000"> _Pr k=
ey_compare</span><span style=3D"color:#660">;</span><span style=3D"color:#0=
00"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">stati=
c</span><span style=3D"color:#000"> </span><span style=3D"color:#008">const=
</span><span style=3D"color:#000"> key_compare comp </span><span style=3D"c=
olor:#660">=3D</span><span style=3D"color:#000"> _Pr</span><span style=3D"c=
olor:#660">();</span><span style=3D"color:#000"><br></span><span style=3D"c=
olor:#008">public</span><span style=3D"color:#660">:</span><span style=3D"c=
olor:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008=
">constexpr</span><span style=3D"color:#000"> const_to_comparison</span><sp=
an style=3D"color:#660">()</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#660">=3D</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#008">default</span><span style=3D"color:#660">;</span><span sty=
le=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"col=
or:#008">constexpr</span><span style=3D"color:#000"> const_to_comparison</s=
pan><span style=3D"color:#660">(</span><span style=3D"color:#008">const</sp=
an><span style=3D"color:#000"> key_type</span><span style=3D"color:#660">&a=
mp;</span><span style=3D"color:#000"> key</span><span style=3D"color:#660">=
)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">:</sp=
an><span style=3D"color:#000"> m_value</span><span style=3D"color:#660">(</=
span><span style=3D"color:#000">key</span><span style=3D"color:#660">)</spa=
n><span style=3D"color:#000"> </span><span style=3D"color:#660">{}</span><s=
pan style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=
=3D"color:#008">constexpr</span><span style=3D"color:#000"> const_to_compar=
ison</span><span style=3D"color:#660">(</span><span style=3D"color:#008">co=
nst</span><span style=3D"color:#000"> _Myt</span><span style=3D"color:#660"=
>&amp;</span><span style=3D"color:#000"> other</span><span style=3D"color:#=
660">)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">=
:</span><span style=3D"color:#000"> m_value</span><span style=3D"color:#660=
">(</span><span style=3D"color:#000">other</span><span style=3D"color:#660"=
>.</span><span style=3D"color:#000">key</span><span style=3D"color:#660">)<=
/span><span style=3D"color:#000"> </span><span style=3D"color:#660">{}</spa=
n><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span s=
tyle=3D"color:#008">constexpr</span><span style=3D"color:#000"> const_to_co=
mparison</span><span style=3D"color:#660">(</span><span style=3D"color:#008=
">const</span><span style=3D"color:#000"> _Myt</span><span style=3D"color:#=
660">&amp;&amp;</span><span style=3D"color:#000"> other</span><span style=
=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#660">:</span><span style=3D"color:#000"> m_value</span><span style=3D=
"color:#660">(</span><span style=3D"color:#000">other</span><span style=3D"=
color:#660">.</span><span style=3D"color:#000">key</span><span style=3D"col=
or:#660">)</span><span style=3D"color:#000"> </span><span style=3D"color:#6=
60">{}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</span><span style=3D"color:#660">&amp;</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#008">operator</spa=
n><span style=3D"color:#660">=3D(</span><span style=3D"color:#000">const_to=
_comparison</span><span style=3D"color:#660">&amp;&amp;</span><span style=
=3D"color:#000"> other</span><span style=3D"color:#660">)</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"c=
olor:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </sp=
an><span style=3D"color:#008">if</span><span style=3D"color:#000"> </span><=
span style=3D"color:#660">(!</span><span style=3D"color:#000">comp</span><s=
pan style=3D"color:#660">(</span><span style=3D"color:#000">m_value</span><=
span style=3D"color:#660">,</span><span style=3D"color:#000"> other</span><=
span style=3D"color:#660">.</span><span style=3D"color:#000">m_value</span>=
<span style=3D"color:#660">))</span><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0std</span><span style=3D"color:#660">::</span><span style=3D"colo=
r:#000">bad_exception</span><span style=3D"color:#660">(</span><span style=
=3D"color:#080">&quot;can&#39;t change this value&quot;</span><span style=
=3D"color:#660">);</span><span style=3D"color:#000"> </span><span style=3D"=
color:#800">//colud be any other exception or simply do nothing</span><span=
 style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 m_value </span><span style=3D"color:#660">=3D</span><span style=3D"c=
olor:#000"> other</span><span style=3D"color:#660">.</span><span style=3D"c=
olor:#000">m_value</span><span style=3D"color:#660">;</span><span style=3D"=
color:#000"> </span><span style=3D"color:#800">//calling move operator=3D</=
span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><spa=
n style=3D"color:#660">}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0=
 =C2=A0 =C2=A0 _Myt</span><span style=3D"color:#660">&amp;</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#008">operator</span><span st=
yle=3D"color:#660">=3D(</span><span style=3D"color:#000">const_to_compariso=
n</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#000"> =
other</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>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=
=3D"color:#008">if</span><span style=3D"color:#000"> </span><span style=3D"=
color:#660">(!</span><span style=3D"color:#000">comp</span><span style=3D"c=
olor:#660">(</span><span style=3D"color:#000">m_value</span><span style=3D"=
color:#660">,</span><span style=3D"color:#000"> other</span><span style=3D"=
color:#660">.</span><span style=3D"color:#000">m_value</span><span style=3D=
"color:#660">))</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0std</s=
pan><span style=3D"color:#660">::</span><span style=3D"color:#000">bad_exce=
ption</span><span style=3D"color:#660">(</span><span style=3D"color:#080">&=
quot;can&#39;t change this value&quot;</span><span style=3D"color:#660">);<=
/span><span style=3D"color:#000"> </span><span style=3D"color:#800">//colud=
 be any other exception or simply do nothing</span><span style=3D"color:#00=
0"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 m_value </sp=
an><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> other</=
span><span style=3D"color:#660">.</span><span style=3D"color:#000">m_value<=
/span><span style=3D"color:#660">;</span><span style=3D"color:#000"> </span=
><span style=3D"color:#800">//calling copy operator=3D</span><span style=3D=
"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#6=
60">}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </sp=
an><span style=3D"color:#008">operator</span><span style=3D"color:#000"> </=
span><span style=3D"color:#008">const</span><span style=3D"color:#000"> _Kt=
y</span><span style=3D"color:#660">&amp;()</span><span style=3D"color:#000"=
> </span><span style=3D"color:#660">{</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#800">//for casting to the container&#39;s value_t=
ype inside the iterator</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008"=
>return</span><span style=3D"color:#000"> m_value</span><span style=3D"colo=
r:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
</span><span style=3D"color:#660">}</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660">~</span><span=
 style=3D"color:#000">const_to_comparison</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:#008">default=
</span><span style=3D"color:#660">;</span><span style=3D"color:#000"><br></=
span><span style=3D"color:#008">private</span><span style=3D"color:#660">:<=
/span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 key_type m=
_value</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></span><span style=3D"color:#660">}</span></div></code></div><div style=
=3D"font-family:monospace;background-color:rgb(250,250,250)"><br></div><div=
>For unordered containers this obviously wouldn&#39;t work since the hash v=
alue would change every time the key changes and so will the position in th=
e container, and this whole mechanism will fail.</div><div>Therefore the ha=
sh value must remain constant after equal key replacement, so I tried to so=
lve it the simplest way I could think of (I don&#39;t really like this solu=
tion so feel free to rip it to shreds):</div><div>Save the hash value of th=
e original object in another field and overload std::hash of this wrapper c=
lass to return this field.</div><div>Something like this:</div><div style=
=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;background-color=
:rgb(250,250,250)"><code><div><span style=3D"color:#000"><br></span><span s=
tyle=3D"color:#008">namespace</span><span style=3D"color:#000"> std </span>=
<span style=3D"color:#660">{</span><span style=3D"color:#000"><br></span><s=
pan style=3D"color:#008">template</span><span style=3D"color:#660">&lt;</sp=
an><span style=3D"color:#008">class</span><span style=3D"color:#000"> _Kty<=
/span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </span=
><span style=3D"color:#606">Compare</span><span style=3D"color:#000"> _Pr <=
/span><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> std<=
/span><span style=3D"color:#660">::</span><span style=3D"color:#000">equal_=
to</span><span style=3D"color:#660">&lt;</span><span style=3D"color:#000">_=
Kty</span><span style=3D"color:#660">&gt;,</span><span style=3D"color:#000"=
> </span><span style=3D"color:#606">Hash</span><span style=3D"color:#000"> =
_Hasher </span><span style=3D"color:#660">=3D</span><span style=3D"color:#0=
00"> std</span><span style=3D"color:#660">::</span><span style=3D"color:#00=
0">hash</span><span style=3D"color:#660">&lt;</span><span style=3D"color:#0=
00">_Kty</span><span style=3D"color:#660">&gt;</span><span style=3D"color:#=
000"> </span><span style=3D"color:#660">&gt;</span><span style=3D"color:#00=
0"><br></span><span style=3D"color:#008">class</span><span style=3D"color:#=
000"> const_to_comparison_and_hash_value </span><span style=3D"color:#660">=
:</span><span style=3D"color:#000"> </span><span style=3D"color:#008">publi=
c</span><span style=3D"color:#000"> const_to_comparison </span><span style=
=3D"color:#660">&lt;</span><span style=3D"color:#000"> _Kty</span><span sty=
le=3D"color:#660">,</span><span style=3D"color:#000"> _Pr </span><span styl=
e=3D"color:#660">&gt;</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0=
 =C2=A0 </span><span style=3D"color:#008">typedef</span><span style=3D"colo=
r:#000"> const_to_comparison</span><span style=3D"color:#660">&lt;</span><s=
pan style=3D"color:#000"> _Kty</span><span style=3D"color:#660">,</span><sp=
an style=3D"color:#000"> _Pr</span><span style=3D"color:#660">&gt;</span><s=
pan style=3D"color:#000"> _Mybase</span><span style=3D"color:#660">;</span>=
<span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span sty=
le=3D"color:#008">typedef</span><span style=3D"color:#000"> const_to_compar=
ison_and_hash_value</span><span style=3D"color:#660">&lt;</span><span style=
=3D"color:#000">_Kty</span><span style=3D"color:#660">,</span><span style=
=3D"color:#000"> _Pr</span><span style=3D"color:#660">,</span><span style=
=3D"color:#000"> _Hasher</span><span style=3D"color:#660">&gt;</span><span =
style=3D"color:#000"> _Myt</span><span style=3D"color:#660">;</span><span s=
tyle=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"c=
olor:#008">typedef</span><span style=3D"color:#000"> _Kty key_type</span><s=
pan style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typedef</span><span sty=
le=3D"color:#000"> _Pr key_compare</span><span style=3D"color:#660">;</span=
><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span st=
yle=3D"color:#008">typedef</span><span style=3D"color:#000"> _Hasher key_ha=
sh</span><span style=3D"color:#660">;</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">static</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#008">const</span><=
span style=3D"color:#000"> key_hash hash </span><span style=3D"color:#660">=
=3D</span><span style=3D"color:#000"> _Hasher</span><span style=3D"color:#6=
60">();</span><span style=3D"color:#000"><br></span><span style=3D"color:#0=
08">public</span><span style=3D"color:#660">:</span><span style=3D"color:#0=
00"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">const=
expr</span><span style=3D"color:#000"> const_to_comparison_and_hash_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"> _Mybase</sp=
an><span style=3D"color:#660">()</span><span style=3D"color:#000"> </span><=
span style=3D"color:#660">{}</span><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</span><spa=
n style=3D"color:#000"> const_to_comparison_and_hash_value</span><span styl=
e=3D"color:#660">(</span><span style=3D"color:#008">const</span><span style=
=3D"color:#000"> key_type</span><span style=3D"color:#660">&amp;</span><spa=
n style=3D"color:#000"> other</span><span style=3D"color:#660">)</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#660">:</span><span sty=
le=3D"color:#000"> _Mybase</span><span style=3D"color:#660">(</span><span s=
tyle=3D"color:#000">other</span><span style=3D"color:#660">)</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#660">{}</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color=
:#008">constexpr</span><span style=3D"color:#000"> const_to_comparison_and_=
hash_value</span><span style=3D"color:#660">(</span><span style=3D"color:#0=
08">const</span><span style=3D"color:#000"> _Mybase</span><span style=3D"co=
lor:#660">&amp;</span><span style=3D"color:#000"> other</span><span style=
=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#660">:</span><span style=3D"color:#000"> _Mybase</span><span style=3D=
"color:#660">(</span><span style=3D"color:#000">other</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>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
</span><span style=3D"color:#008">constexpr</span><span style=3D"color:#000=
"> const_to_comparison_and_hash_value</span><span style=3D"color:#660">(</s=
pan><span style=3D"color:#008">const</span><span style=3D"color:#000"> _Myt=
</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#000"> o=
ther</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> <=
/span><span style=3D"color:#660">:</span><span style=3D"color:#000"> _Mybas=
e</span><span style=3D"color:#660">(</span><span style=3D"color:#000">other=
</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#660">{}</span><span style=3D"color:#000"><br>=C2=A0=
 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</span><sp=
an style=3D"color:#000"> const_to_comparison_and_hash_value</span><span sty=
le=3D"color:#660">(</span><span style=3D"color:#008">const</span><span styl=
e=3D"color:#000"> _Myt</span><span style=3D"color:#660">&amp;&amp;</span><s=
pan style=3D"color:#000"> other</span><span style=3D"color:#660">)</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#660">:</span><span s=
tyle=3D"color:#000"> _Mybase</span><span style=3D"color:#660">(</span><span=
 style=3D"color:#000">other</span><span style=3D"color:#660">)</span><span =
style=3D"color:#000"> </span><span style=3D"color:#660">{}</span><span styl=
e=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</span><span style=3D"=
color:#660">&amp;</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#008">operator</span><span style=3D"color:#660">=3D(</span><span style=
=3D"color:#008">const</span><span style=3D"color:#000"> _Myt</span><span st=
yle=3D"color:#660">&amp;</span><span style=3D"color:#000"> other</span><spa=
n style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">th=
is</span><span style=3D"color:#660">-&gt;</span><span style=3D"color:#000">=
_Mybase</span><span style=3D"color:#660">::</span><span style=3D"color:#008=
">operator</span><span style=3D"color:#660">=3D((</span><span style=3D"colo=
r:#008">const</span><span style=3D"color:#000"> _Mybase</span><span style=
=3D"color:#660">&amp;)</span><span style=3D"color:#000">other</span><span s=
tyle=3D"color:#660">);</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span style=3D"colo=
r:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</span><span style=3D"color:#66=
0">&amp;</span><span style=3D"color:#000"> </span><span style=3D"color:#008=
">operator</span><span style=3D"color:#660">=3D(</span><span style=3D"color=
:#008">const</span><span style=3D"color:#000"> _Myt</span><span style=3D"co=
lor:#660">&amp;&amp;</span><span style=3D"color:#000"> other</span><span st=
yle=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0=
 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#008">this</=
span></div></code></div></div>...</blockquote></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&quot; 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_16_591603680.1436986291496--
------=_Part_15_1787304585.1436986291490--

.


Author: vinnie@ripple.com
Date: Wed, 15 Jul 2015 16:48:50 -0700 (PDT)
Raw View
------=_Part_217_357466078.1437004130372
Content-Type: multipart/alternative;
 boundary="----=_Part_218_131855100.1437004130372"

------=_Part_218_131855100.1437004130372
Content-Type: text/plain; charset=UTF-8

On Tuesday, July 14, 2015 at 1:23:45 PM UTC-7, Omer Rosler wrote:
>
> This post is an attempt to partially solve the problem of key replacement
>  in (unordered) associative containers such as
> (unordered_)(multi)map, (unordered_)(multi)set* when the object doesn't
> move inside the container after replacement and the value *up to the
> comparator* is the same.
>

I think this is a worthwhile goal, but note that this proposal from two
years ago solves that problem and much more:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3586.pdf

I'm fond of this approach, it provides much needed functionality in the
standard library that one would otherwise have to resort to
boost::intrusive to get (in addition to writing a lot of boilerplate).

--

---
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_218_131855100.1437004130372
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Tuesday, July 14, 2015 at 1:23:45 PM UTC-7, Omer Rosler=
 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>T=
his post is an attempt to partially solve the problem of key replacement =
=C2=A0in (unordered) associative containers such as<br></div><div>(unordere=
d_)(multi)map, (unordered_)(multi)set* when the object doesn&#39;t move ins=
ide the container after replacement and the value <b>up to the comparator</=
b> is the same.</div></div></blockquote><div><br></div><div>I think this is=
 a worthwhile goal, but note that this proposal from two years ago solves t=
hat problem and much more:</div><div>http://www.open-std.org/jtc1/sc22/wg21=
/docs/papers/2013/n3586.pdf<br></div><div><br></div><div>I&#39;m fond of th=
is approach, it provides much needed functionality in the standard library =
that one would otherwise have to resort to boost::intrusive to get (in addi=
tion to writing a lot of boilerplate).</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&quot; 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_218_131855100.1437004130372--
------=_Part_217_357466078.1437004130372--

.


Author: Edward Catmur <ed@catmur.co.uk>
Date: Thu, 16 Jul 2015 02:06:55 -0700 (PDT)
Raw View
------=_Part_540_394702357.1437037615995
Content-Type: multipart/alternative;
 boundary="----=_Part_541_2129426335.1437037615997"

------=_Part_541_2129426335.1437037615997
Content-Type: text/plain; charset=UTF-8

That's why I was looking for an example - I find it difficult to envisage a
type that has values equivalent under incomparability or under equality but
with different hashes; if you're having to save the original hash value
then wouldn't you also have to save the entire original value for use with
equality or strict weak comparators?

On Wednesday, 15 July 2015 19:51:31 UTC+1, Omer Rosler wrote:
>
> Because the underlying object inside the underlying class can change and
> therefore also it's hash value, so the object will not be in the designated
> place in the container by simply using the hash function.
> In your example there are two hashers: std::hash<int> and the lambda you
> defined taking the hash value of the modulus of the object.
> For user defined types 2 hashers must be created, unlike unmutable keys.
> What I want to do is to create a template that for every comparator
> returns an equal hash value for equal elements (one template).
> Your lambda is the solution for the specific comparator you defined, I'm
> looking for a general solution.
> The only one I can think of is saving the original hash value.
>
> On Tuesday, July 14, 2015 at 11:23:45 PM UTC+3, Omer Rosler wrote:
>>
>> This is the first time I share my ideas about C++, so don't be too harsh
>> :)
>> This post is an attempt to partially solve the problem of key replacement
>>  in (unordered) associative containers such as
>> (unordered_)(multi)map, (unordered_)(multi)set* when the object doesn't
>> move inside the container after replacement and the value *up to the
>> comparator* is the same.
>> *The braces () mean optiopnal.
>> Note that in ordered containers if the value doesn't change (up to the
>> comparator) so does the position of the object; in unordered this gets
>> trickier, but we'll get to that later.
>> My aproach is to create an intermediate class that provides a const-like
>> access to a object but allows changing it if a comparator yields true (so
>> the complexity of the assignment operator is the maximum of the complexity
>> of the object type's assignemnt operator, and the comparator's complexity).
>> In case of setting a diffrent value this class can either throw some
>> exception or simply do nothing (up for debate).
>> By using this class inside the underlying RB tree as the value type
>> (instead of a simple const type) it will allow iterators to change the
>> value of the key they hold by calling the wrapper class's assignemnt
>> iterator.
>> I haven't decided whether it's smart to make this class public and change
>> the containers' value type (meaning: big diffrence from older versions for
>> all 8 containers, although the conversion operator makes old code work all
>> the same), or simply make it private and convert to container's value type
>> inside the iterators which will now have setter functions.
>> The second option has major downsides: The current iterators interface
>> needs to be changed, instead of holding const key as a public member (like
>> it does now), it will hold this wrapper class as a private/protected
>> member, and accessing it must be done using a function call to a getter
>> that calls a conversion operator (so access is using funtion calls only,
>> instead of accessing a public member):
>> template<class Key_type, Compare Comparator = std::equal_to<Key_type> >
>> struct iterator {
>>         //other code...
>>         const Key_type& key() const { //getter
>>                 return m_value; //call conversion operator
>>         }
>>         const Key_type& key(const Key_type&x) { //setter
>>                 return m_value = x; //call copy assignment operator of
>> wrapper class
>>         }
>> private:
>>         const_to_comparison<Key_type, Comparator> m_value
>> };
>>
>> (The name 'key' isn't the real function name, for map iterator it will be
>> 'first', and for the set iterator it will be operator* for getter and set
>> (maybe not a good name in this case) for setter)
>> It is possible to be made compatible with other versions but will make
>> the container to hold another public member for the converted type which
>> takes twice the memory it used to.
>> So maybe the first option where this wrapper class is public is better
>> (at least in my opinion).
>> Maybe there are other places this const-like access can be used.
>> Well, the wrapper looks basically like this:
>>
>> namespace std {
>> template<class _Kty, Compare _Pr = std::equal_to<_Kty> >
>> class const_to_comparison {
>>         typedef const_to_comparison<_Kty, _Pr> _Myt;
>>         typedef _Kty key_type;
>>         typedef _Pr key_compare;
>>         static const key_compare comp = _Pr();
>> public:
>>         constexpr const_to_comparison() = default;
>>         constexpr const_to_comparison(const key_type& key) : m_value(key)
>> {}
>>         constexpr const_to_comparison(const _Myt& other) : m_value(other.
>> key) {}
>>         constexpr const_to_comparison(const _Myt&& other) : m_value(other
>> .key) {}
>>                 _Myt& operator=(const_to_comparison&& other) {
>>                 if (!comp(m_value, other.m_value))
>>                          std::bad_exception("can't change this value"); //colud
>> be any other exception or simply do nothing
>>                 m_value = other.m_value; //calling move operator=
>>         }
>>         _Myt& operator=(const_to_comparison& other) {
>>                 if (!comp(m_value, other.m_value))
>>                          std::bad_exception("can't change this value"); //colud
>> be any other exception or simply do nothing
>>                 m_value = other.m_value; //calling copy operator=
>>         }
>>         operator const _Kty&() { //for casting to the container's
>> value_type inside the iterator
>>                 return m_value;
>>         }
>>         ~const_to_comparison() = default;
>> private:
>>         key_type m_value;
>> };
>> }
>>
>> For unordered containers this obviously wouldn't work since the hash
>> value would change every time the key changes and so will the position in
>> the container, and this whole mechanism will fail.
>> Therefore the hash value must remain constant after equal key
>> replacement, so I tried to solve it the simplest way I could think of (I
>> don't really like this solution so feel free to rip it to shreds):
>> Save the hash value of the original object in another field and overload
>> std::hash of this wrapper class to return this field.
>> Something like this:
>>
>> namespace std {
>> template<class _Kty, Compare _Pr = std::equal_to<_Kty>, Hash _Hasher =
>> std::hash<_Kty> >
>> class const_to_comparison_and_hash_value : public const_to_comparison <
>> _Kty, _Pr > {
>>         typedef const_to_comparison< _Kty, _Pr> _Mybase;
>>         typedef const_to_comparison_and_hash_value<_Kty, _Pr, _Hasher>
>> _Myt;
>>         typedef _Kty key_type;
>>         typedef _Pr key_compare;
>>         typedef _Hasher key_hash;
>>         static const key_hash hash = _Hasher();
>> public:
>>         constexpr const_to_comparison_and_hash_value() : _Mybase() {}
>>         constexpr const_to_comparison_and_hash_value(const key_type&
>> other) : _Mybase(other) {}
>>         constexpr const_to_comparison_and_hash_value(const _Mybase& other
>> ) : _Mybase(other) {}
>>         constexpr const_to_comparison_and_hash_value(const _Myt& other) :
>> _Mybase(other) {}
>>         constexpr const_to_comparison_and_hash_value(const _Myt&& other)
>> : _Mybase(other) {}
>>         _Myt& operator=(const _Myt& other) {
>>                 this->_Mybase::operator=((const _Mybase&)other);
>>         }
>>         _Myt& operator=(const _Myt&& other) {
>>                this
>> ...
>
>

--

---
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_541_2129426335.1437037615997
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">That&#39;s why I was looking for an example - I find it di=
fficult to envisage a type that has values equivalent under incomparability=
 or under equality but with different hashes; if you&#39;re having to save =
the original hash value then wouldn&#39;t you also have to save the entire =
original value for use with equality or strict weak comparators?<br><br>On =
Wednesday, 15 July 2015 19:51:31 UTC+1, Omer Rosler  wrote:<blockquote clas=
s=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #c=
cc solid;padding-left: 1ex;"><div dir=3D"ltr">Because the underlying object=
 inside the underlying class can change and therefore also it&#39;s hash va=
lue, so the object will not be in the designated place in the container by =
simply using the hash function.<div>In your example there are two hashers: =
std::hash&lt;int&gt; and the lambda you defined taking the hash value of th=
e modulus of the object.</div><div>For user defined types 2 hashers must be=
 created, unlike unmutable keys.</div><div>What I want to do is to create a=
 template that for every comparator returns an equal hash value for equal e=
lements (one template).</div><div>Your lambda is the solution for the speci=
fic comparator you defined, I&#39;m looking for a general solution.</div><d=
iv>The only one I can think of is saving the original hash value.</div><div=
><br>On Tuesday, July 14, 2015 at 11:23:45 PM UTC+3, Omer Rosler wrote:<blo=
ckquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-le=
ft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>This is the first=
 time I share my ideas about C++, so don&#39;t be too harsh :)<br></div><di=
v>This post is an attempt to partially solve the problem of key replacement=
 =C2=A0in (unordered) associative containers such as</div><div>(unordered_)=
(multi)map, (unordered_)(multi)set* when the object doesn&#39;t move inside=
 the container after replacement and the value <b>up to the comparator</b> =
is the same.</div><div>*The braces () mean optiopnal.</div><div>Note that i=
n ordered containers if the value doesn&#39;t change (up to the comparator)=
 so does the position of the object; in unordered this gets trickier, but w=
e&#39;ll get to that later.</div><div>My aproach is to create an intermedia=
te class that provides a const-like access to a object but allows changing =
it if a comparator yields true (so the complexity of the assignment operato=
r is the maximum of the complexity of the object type&#39;s assignemnt oper=
ator, and the comparator&#39;s complexity).</div><div>In case of setting a =
diffrent value this class can either throw some exception or simply do noth=
ing (up for debate).</div><div>By using this class inside the underlying RB=
 tree as the value type (instead of a simple const type) it will allow iter=
ators to change the value of the key they hold by calling the wrapper class=
&#39;s assignemnt iterator.</div><div>I haven&#39;t decided whether it&#39;=
s smart to make this class public and change the containers&#39; value type=
 (meaning: big diffrence from older versions for all 8 containers, although=
 the conversion operator makes old code work all the same), or simply make =
it private and convert to container&#39;s value type inside the iterators w=
hich will now have setter functions.</div><div>The second option has major =
downsides: The current iterators interface needs to be changed, instead of =
holding const key as a public member (like it does now), it will hold this =
wrapper class as a private/protected member, and accessing it must be done =
using a function call to a getter that calls a conversion operator (so acce=
ss is using funtion calls only, instead of accessing a public member):</div=
><div><div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;=
background-color:rgb(250,250,250)"><code><div><span style=3D"color:#008">te=
mplate</span><span style=3D"color:#660">&lt;</span><span style=3D"color:#00=
8">class</span><span style=3D"color:#000"> </span><span style=3D"color:#606=
">Key_type</span><span style=3D"color:#660">,</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#606">Compare</span><span style=3D"color:#=
000"> </span><span style=3D"color:#606">Comparator</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#660">=3D</span><span style=3D"color:=
#000"> std</span><span style=3D"color:#660">::</span><span style=3D"color:#=
000">equal_to</span><span style=3D"color:#660">&lt;</span><span style=3D"co=
lor:#606">Key_type</span><span style=3D"color:#660">&gt;</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">&gt;</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#008">struct</span><span st=
yle=3D"color:#000"> iterator </span><span style=3D"color:#660">{</span><spa=
n style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=
=3D"color:#800">//other code...</span><span style=3D"color:#000"><br>=C2=A0=
 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">const</span><span s=
tyle=3D"color:#000"> </span><span style=3D"color:#606">Key_type</span><span=
 style=3D"color:#660">&amp;</span><span style=3D"color:#000"> key</span><sp=
an style=3D"color:#660">()</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#008">const</span><font color=3D"#666600"><span style=3D"colo=
r:#000"> </span><span style=3D"color:#660">{</span></font><span style=3D"co=
lor:#000"> </span><span style=3D"color:#800">//getter</span><span style=3D"=
color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </s=
pan><span style=3D"color:#008">return</span><span style=3D"color:#000"> m_v=
alue</span><span style=3D"color:#660">;</span><span style=3D"color:#000"> <=
/span><span style=3D"color:#800">//</span><font color=3D"#000000"><span sty=
le=3D"color:#800">call conversion operator</span><span style=3D"color:#000"=
><br></span></font><span style=3D"color:#000">=C2=A0 =C2=A0 =C2=A0 =C2=A0 <=
/span><span style=3D"color:#660">}</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">const</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#606">Key_type</span><s=
pan style=3D"color:#660">&amp;</span><span style=3D"color:#000"> key</span>=
<span style=3D"color:#660">(</span><span style=3D"color:#008">const</span><=
span style=3D"color:#000"> </span><span style=3D"color:#606">Key_type</span=
><span style=3D"color:#660">&amp;</span><span style=3D"color:#000">x</span>=
<span style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span=
 style=3D"color:#660">{</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#800">//setter</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#=
008">return</span><span style=3D"color:#000"> m_value </span><span style=3D=
"color:#660">=3D</span><span style=3D"color:#000"> x</span><span style=3D"c=
olor:#660">;</span><span style=3D"color:#000"> </span><span style=3D"color:=
#800">//call copy assignment operator of wrapper class</span><span style=3D=
"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#6=
60">}</span><span style=3D"color:#000"><br></span><span style=3D"color:#008=
">private</span><span style=3D"color:#660">:</span><span style=3D"color:#00=
0"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 const_to_comparison</span><span style=3D=
"color:#660">&lt;</span><span style=3D"color:#606">Key_type</span><span sty=
le=3D"color:#660">,</span><span style=3D"color:#000"> </span><span style=3D=
"color:#606">Comparator</span><span style=3D"color:#660">&gt;</span><span s=
tyle=3D"color:#000"> m_value<br></span><span style=3D"color:#660">};</span>=
<font color=3D"#666600"></font></div></code></div></div><div><br></div><div=
>(The name &#39;key&#39; isn&#39;t the real function name, for map iterator=
 it will be &#39;first&#39;, and for the set iterator it will be operator* =
for getter and set (maybe not a good name in this case) for setter)</div><d=
iv>It is possible to be made compatible with other versions but will make t=
he container to hold another public member for the converted type which tak=
es twice the memory it used to.</div><div>So maybe the first option where t=
his wrapper class is public is better (at least in my opinion).</div><div>M=
aybe there are other places this const-like access can be used.</div><div>W=
ell, the wrapper looks basically like this:</div><div><br></div><div style=
=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;background-color=
:rgb(250,250,250)"><code><div><span style=3D"color:#008">namespace</span><s=
pan style=3D"color:#000"> std </span><span style=3D"color:#660">{</span><sp=
an style=3D"color:#000"><br></span><span style=3D"color:#008">template</spa=
n><span style=3D"color:#660">&lt;</span><span style=3D"color:#008">class</s=
pan><span style=3D"color:#000"> _Kty</span><span style=3D"color:#660">,</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#606">Compare</s=
pan><span style=3D"color:#000"> _Pr </span><span style=3D"color:#660">=3D</=
span><span style=3D"color:#000"> std</span><span style=3D"color:#660">::</s=
pan><span style=3D"color:#000">equal_to</span><span style=3D"color:#660">&l=
t;</span><span style=3D"color:#000">_Kty</span><span style=3D"color:#660">&=
gt;</span><span style=3D"color:#000"> </span><span style=3D"color:#660">&gt=
;</span><span style=3D"color:#000"><br></span><span style=3D"color:#008">cl=
ass</span><span style=3D"color:#000"> const_to_comparison </span><span styl=
e=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 </span><span style=3D"color:#008">typedef</span><span style=3D"c=
olor:#000"> const_to_comparison</span><span style=3D"color:#660">&lt;</span=
><span style=3D"color:#000">_Kty</span><span style=3D"color:#660">,</span><=
span style=3D"color:#000"> _Pr</span><span style=3D"color:#660">&gt;</span>=
<span style=3D"color:#000"> _Myt</span><span style=3D"color:#660">;</span><=
span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span styl=
e=3D"color:#008">typedef</span><span style=3D"color:#000"> _Kty key_type</s=
pan><span style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typedef</span><s=
pan style=3D"color:#000"> _Pr key_compare</span><span style=3D"color:#660">=
;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><=
span style=3D"color:#008">static</span><span style=3D"color:#000"> </span><=
span style=3D"color:#008">const</span><span style=3D"color:#000"> key_compa=
re comp </span><span style=3D"color:#660">=3D</span><span style=3D"color:#0=
00"> _Pr</span><span style=3D"color:#660">();</span><span style=3D"color:#0=
00"><br></span><span style=3D"color:#008">public</span><span style=3D"color=
:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 <=
/span><span style=3D"color:#008">constexpr</span><span style=3D"color:#000"=
> const_to_comparison</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:#008">default</span><span style=
=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0=
 =C2=A0 </span><span style=3D"color:#008">constexpr</span><span style=3D"co=
lor:#000"> const_to_comparison</span><span style=3D"color:#660">(</span><sp=
an style=3D"color:#008">const</span><span style=3D"color:#000"> key_type</s=
pan><span style=3D"color:#660">&amp;</span><span style=3D"color:#000"> key<=
/span><span style=3D"color:#660">)</span><span style=3D"color:#000"> </span=
><span style=3D"color:#660">:</span><span style=3D"color:#000"> m_value</sp=
an><span style=3D"color:#660">(</span><span style=3D"color:#000">key</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>=C2=A0 =C2=A0=
 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</span><span styl=
e=3D"color:#000"> const_to_comparison</span><span style=3D"color:#660">(</s=
pan><span style=3D"color:#008">const</span><span style=3D"color:#000"> _Myt=
</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#000"> o=
ther</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> <=
/span><span style=3D"color:#660">:</span><span style=3D"color:#000"> m_valu=
e</span><span style=3D"color:#660">(</span><span style=3D"color:#000">other=
</span><span style=3D"color:#660">.</span><span style=3D"color:#000">key</s=
pan><span style=3D"color:#660">)</span><span style=3D"color:#000"> </span><=
span style=3D"color:#660">{}</span><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</span><spa=
n style=3D"color:#000"> const_to_comparison</span><span style=3D"color:#660=
">(</span><span style=3D"color:#008">const</span><span style=3D"color:#000"=
> _Myt</span><span style=3D"color:#660">&amp;&amp;</span><span style=3D"col=
or:#000"> other</span><span style=3D"color:#660">)</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#660">:</span><span style=3D"color:#0=
00"> m_value</span><span style=3D"color:#660">(</span><span style=3D"color:=
#000">other</span><span style=3D"color:#660">.</span><span style=3D"color:#=
000">key</span><span style=3D"color:#660">)</span><span style=3D"color:#000=
"> </span><span style=3D"color:#660">{}</span><span style=3D"color:#000"><b=
r>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</span><span =
style=3D"color:#660">&amp;</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#008">operator</span><span style=3D"color:#660">=3D(</span><s=
pan style=3D"color:#000">const_to_comparison</span><span style=3D"color:#66=
0">&amp;&amp;</span><span style=3D"color:#000"> other</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>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">if</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#660">(!</span><span st=
yle=3D"color:#000">comp</span><span style=3D"color:#660">(</span><span styl=
e=3D"color:#000">m_value</span><span style=3D"color:#660">,</span><span sty=
le=3D"color:#000"> other</span><span style=3D"color:#660">.</span><span sty=
le=3D"color:#000">m_value</span><span style=3D"color:#660">))</span><span s=
tyle=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0std</span><span style=3D"color:#66=
0">::</span><span style=3D"color:#000">bad_exception</span><span style=3D"c=
olor:#660">(</span><span style=3D"color:#080">&quot;can&#39;t change this v=
alue&quot;</span><span style=3D"color:#660">);</span><span style=3D"color:#=
000"> </span><span style=3D"color:#800">//colud be any other exception or s=
imply do nothing</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 m_value </span><span style=3D"color:#660=
">=3D</span><span style=3D"color:#000"> other</span><span style=3D"color:#6=
60">.</span><span style=3D"color:#000">m_value</span><span style=3D"color:#=
660">;</span><span style=3D"color:#000"> </span><span style=3D"color:#800">=
//calling move operator=3D</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span style=3D"=
color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</span><span style=3D"color=
:#660">&amp;</span><span style=3D"color:#000"> </span><span style=3D"color:=
#008">operator</span><span style=3D"color:#660">=3D(</span><span style=3D"c=
olor:#000">const_to_comparison</span><span style=3D"color:#660">&amp;</span=
><span style=3D"color:#000"> other</span><span style=3D"color:#660">)</span=
><span style=3D"color:#000"> </span><span style=3D"color:#660">{</span><spa=
n style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
 =C2=A0 </span><span style=3D"color:#008">if</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#660">(!</span><span style=3D"color:#000">c=
omp</span><span style=3D"color:#660">(</span><span style=3D"color:#000">m_v=
alue</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> o=
ther</span><span style=3D"color:#660">.</span><span style=3D"color:#000">m_=
value</span><span style=3D"color:#660">))</span><span style=3D"color:#000">=
<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0std</span><span style=3D"color:#660">::</span><span sty=
le=3D"color:#000">bad_exception</span><span style=3D"color:#660">(</span><s=
pan style=3D"color:#080">&quot;can&#39;t change this value&quot;</span><spa=
n style=3D"color:#660">);</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#800">//colud be any other exception or simply do nothing</spa=
n><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 m_value </span><span style=3D"color:#660">=3D</span><span sty=
le=3D"color:#000"> other</span><span style=3D"color:#660">.</span><span sty=
le=3D"color:#000">m_value</span><span style=3D"color:#660">;</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#800">//calling copy operat=
or=3D</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </sp=
an><span style=3D"color:#660">}</span><span style=3D"color:#000"><br>=C2=A0=
 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">operator</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#008">const</span><span=
 style=3D"color:#000"> _Kty</span><span style=3D"color:#660">&amp;()</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#660">{</span><span=
 style=3D"color:#000"> </span><span style=3D"color:#800">//for casting to t=
he container&#39;s value_type inside the iterator</span><span style=3D"colo=
r:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span>=
<span style=3D"color:#008">return</span><span style=3D"color:#000"> m_value=
</span><span style=3D"color:#660">;</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span=
 style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D=
"color:#660">~</span><span style=3D"color:#000">const_to_comparison</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 st=
yle=3D"color:#008">default</span><span style=3D"color:#660">;</span><span s=
tyle=3D"color:#000"><br></span><span style=3D"color:#008">private</span><sp=
an style=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 key_type m_value</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></span><span style=3D"color:#660">}</span></=
div></code></div><div style=3D"font-family:monospace;background-color:rgb(2=
50,250,250)"><br></div><div>For unordered containers this obviously wouldn&=
#39;t work since the hash value would change every time the key changes and=
 so will the position in the container, and this whole mechanism will fail.=
</div><div>Therefore the hash value must remain constant after equal key re=
placement, so I tried to solve it the simplest way I could think of (I don&=
#39;t really like this solution so feel free to rip it to shreds):</div><di=
v>Save the hash value of the original object in another field and overload =
std::hash of this wrapper class to return this field.</div><div>Something l=
ike this:</div><div style=3D"border:1px solid rgb(187,187,187);word-wrap:br=
eak-word;background-color:rgb(250,250,250)"><code><div><span style=3D"color=
:#000"><br></span><span style=3D"color:#008">namespace</span><span style=3D=
"color:#000"> std </span><span style=3D"color:#660">{</span><span style=3D"=
color:#000"><br></span><span style=3D"color:#008">template</span><span styl=
e=3D"color:#660">&lt;</span><span style=3D"color:#008">class</span><span st=
yle=3D"color:#000"> _Kty</span><span style=3D"color:#660">,</span><span sty=
le=3D"color:#000"> </span><span style=3D"color:#606">Compare</span><span st=
yle=3D"color:#000"> _Pr </span><span style=3D"color:#660">=3D</span><span s=
tyle=3D"color:#000"> std</span><span style=3D"color:#660">::</span><span st=
yle=3D"color:#000">equal_to</span><span style=3D"color:#660">&lt;</span><sp=
an style=3D"color:#000">_Kty</span><span style=3D"color:#660">&gt;,</span><=
span style=3D"color:#000"> </span><span style=3D"color:#606">Hash</span><sp=
an style=3D"color:#000"> _Hasher </span><span style=3D"color:#660">=3D</spa=
n><span style=3D"color:#000"> std</span><span style=3D"color:#660">::</span=
><span style=3D"color:#000">hash</span><span style=3D"color:#660">&lt;</spa=
n><span style=3D"color:#000">_Kty</span><span style=3D"color:#660">&gt;</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#660">&gt;</span=
><span style=3D"color:#000"><br></span><span style=3D"color:#008">class</sp=
an><span style=3D"color:#000"> const_to_comparison_and_hash_value </span><s=
pan style=3D"color:#660">:</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#008">public</span><span style=3D"color:#000"> const_to_compa=
rison </span><span style=3D"color:#660">&lt;</span><span style=3D"color:#00=
0"> _Kty</span><span style=3D"color:#660">,</span><span style=3D"color:#000=
"> _Pr </span><span style=3D"color:#660">&gt;</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#660">{</span><span style=3D"color:#000"><=
br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">typedef</s=
pan><span style=3D"color:#000"> const_to_comparison</span><span style=3D"co=
lor:#660">&lt;</span><span style=3D"color:#000"> _Kty</span><span style=3D"=
color:#660">,</span><span style=3D"color:#000"> _Pr</span><span style=3D"co=
lor:#660">&gt;</span><span style=3D"color:#000"> _Mybase</span><span style=
=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0=
 =C2=A0 </span><span style=3D"color:#008">typedef</span><span style=3D"colo=
r:#000"> const_to_comparison_and_hash_value</span><span style=3D"color:#660=
">&lt;</span><span style=3D"color:#000">_Kty</span><span style=3D"color:#66=
0">,</span><span style=3D"color:#000"> _Pr</span><span style=3D"color:#660"=
>,</span><span style=3D"color:#000"> _Hasher</span><span style=3D"color:#66=
0">&gt;</span><span style=3D"color:#000"> _Myt</span><span style=3D"color:#=
660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </s=
pan><span style=3D"color:#008">typedef</span><span style=3D"color:#000"> _K=
ty key_type</span><span style=3D"color:#660">;</span><span style=3D"color:#=
000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">type=
def</span><span style=3D"color:#000"> _Pr key_compare</span><span style=3D"=
color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 </span><span style=3D"color:#008">typedef</span><span style=3D"color:#0=
00"> _Hasher key_hash</span><span style=3D"color:#660">;</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color=
:#008">static</span><span style=3D"color:#000"> </span><span style=3D"color=
:#008">const</span><span style=3D"color:#000"> key_hash hash </span><span s=
tyle=3D"color:#660">=3D</span><span style=3D"color:#000"> _Hasher</span><sp=
an style=3D"color:#660">();</span><span style=3D"color:#000"><br></span><sp=
an style=3D"color:#008">public</span><span style=3D"color:#660">:</span><sp=
an style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=
=3D"color:#008">constexpr</span><span style=3D"color:#000"> const_to_compar=
ison_and_hash_value</span><span style=3D"color:#660">()</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">:</span><span style=3D"c=
olor:#000"> _Mybase</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>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#00=
8">constexpr</span><span style=3D"color:#000"> const_to_comparison_and_hash=
_value</span><span style=3D"color:#660">(</span><span style=3D"color:#008">=
const</span><span style=3D"color:#000"> key_type</span><span style=3D"color=
:#660">&amp;</span><span style=3D"color:#000"> other</span><span style=3D"c=
olor:#660">)</span><span style=3D"color:#000"> </span><span style=3D"color:=
#660">:</span><span style=3D"color:#000"> _Mybase</span><span style=3D"colo=
r:#660">(</span><span style=3D"color:#000">other</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>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </spa=
n><span style=3D"color:#008">constexpr</span><span style=3D"color:#000"> co=
nst_to_comparison_and_hash_value</span><span style=3D"color:#660">(</span><=
span style=3D"color:#008">const</span><span style=3D"color:#000"> _Mybase</=
span><span style=3D"color:#660">&amp;</span><span style=3D"color:#000"> oth=
er</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#660">:</span><span style=3D"color:#000"> _Mybase<=
/span><span style=3D"color:#660">(</span><span style=3D"color:#000">other</=
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>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">constexpr</span><spa=
n style=3D"color:#000"> const_to_comparison_and_hash_value</span><span styl=
e=3D"color:#660">(</span><span style=3D"color:#008">const</span><span style=
=3D"color:#000"> _Myt</span><span style=3D"color:#660">&amp;</span><span st=
yle=3D"color:#000"> other</span><span style=3D"color:#660">)</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#660">:</span><span style=
=3D"color:#000"> _Mybase</span><span style=3D"color:#660">(</span><span sty=
le=3D"color:#000">other</span><span style=3D"color:#660">)</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#660">{}</span><span style=3D=
"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#0=
08">constexpr</span><span style=3D"color:#000"> const_to_comparison_and_has=
h_value</span><span style=3D"color:#660">(</span><span style=3D"color:#008"=
>const</span><span style=3D"color:#000"> _Myt</span><span style=3D"color:#6=
60">&amp;&amp;</span><span style=3D"color:#000"> other</span><span style=3D=
"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"colo=
r:#660">:</span><span style=3D"color:#000"> _Mybase</span><span style=3D"co=
lor:#660">(</span><span style=3D"color:#000">other</span><span style=3D"col=
or:#660">)</span><span style=3D"color:#000"> </span><span style=3D"color:#6=
60">{}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 _My=
t</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#000"> =
</span><span style=3D"color:#008">operator</span><span style=3D"color:#660"=
>=3D(</span><span style=3D"color:#008">const</span><span style=3D"color:#00=
0"> _Myt</span><span style=3D"color:#660">&amp;</span><span style=3D"color:=
#000"> other</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>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span s=
tyle=3D"color:#008">this</span><span style=3D"color:#660">-&gt;</span><span=
 style=3D"color:#000">_Mybase</span><span style=3D"color:#660">::</span><sp=
an style=3D"color:#008">operator</span><span style=3D"color:#660">=3D((</sp=
an><span style=3D"color:#008">const</span><span style=3D"color:#000"> _Myba=
se</span><span style=3D"color:#660">&amp;)</span><span style=3D"color:#000"=
>other</span><span style=3D"color:#660">);</span><span style=3D"color:#000"=
><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span>=
<span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 _Myt</span><span=
 style=3D"color:#660">&amp;</span><span style=3D"color:#000"> </span><span =
style=3D"color:#008">operator</span><span style=3D"color:#660">=3D(</span><=
span style=3D"color:#008">const</span><span style=3D"color:#000"> _Myt</spa=
n><span style=3D"color:#660">&amp;&amp;</span><span style=3D"color:#000"> o=
ther</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>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"c=
olor:#008">this</span></div></code></div></div>...</blockquote></div></div>=
</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&quot; 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_541_2129426335.1437037615997--
------=_Part_540_394702357.1437037615995--

.


Author: Omer Rosler <omer.rosler@gmail.com>
Date: Thu, 16 Jul 2015 03:04:16 -0700 (PDT)
Raw View
------=_Part_497_276833959.1437041056788
Content-Type: multipart/alternative;
 boundary="----=_Part_498_455528457.1437041056789"

------=_Part_498_455528457.1437041056789
Content-Type: text/plain; charset=UTF-8

On Thursday, July 16, 2015 at 12:06:56 PM UTC+3, Edward Catmur wrote:
>
> That's why I was looking for an example - I find it difficult to envisage
> a type that has values equivalent under incomparability or under equality
> but with different hashes; if you're having to save the original hash value
> then wouldn't you also have to save the entire original value for use with
> equality or strict weak comparators?
>
> First, hasher is supposed to return diffrent values for objects that are
not *exactly* the same, that's the whole point of the hasher, and the whole
problem of this mutable-wrapper mechanism.
To define a "pseudo-hasher", that is a function returns equal results only
for equivalent results up to some comparison, by using a real hash of the
type is the goal here.
I wouldn't have to save the original object if the value is always
equivalent, the unordered container insepcts the mutable type with only two
functions:
1. The comparator which will return the same as if you compared to the
original object (since the changed object is equal to the original one).
2. The hasher which will always return the hash value of the original
object, after it will be saved somewhere (or maybe create a "pseudo-hasher"
in some other way, that has the same effect).
Therefore, form the containert's perspective the object was never changed,
and so does it's position in the container. If by accident the hash value
of the object was changed, the object must be moved, otherwise the
container will be broken, using this "pseudo-hahser" will stop that from
happening.

I think this is a worthwhile goal, but note that this proposal from two
> years ago solves that problem and much more:
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3586.pdf
>
> I'm fond of this approach, it provides much needed functionality in the
> standard library that one would otherwise have to resort to
> boost::intrusive to get (in addition to writing a lot of boilerplate).
>

This proposal is indeed much more extensive than the ideas in this thread,
however I can't seem to find information why it was rejected (I assume it
was, since this isn't part of the standard library today). Where can I find
this information?

--

---
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_498_455528457.1437041056789
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Thursday, July 16, 2015 at 12:06:56 PM UTC+3, Edward Ca=
tmur 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">Th=
at&#39;s why I was looking for an example - I find it difficult to envisage=
 a type that has values equivalent under incomparability or under equality =
but with different hashes; if you&#39;re having to save the original hash v=
alue then wouldn&#39;t you also have to save the entire original value for =
use with equality or strict weak comparators?<br><br></div></blockquote><di=
v>First, hasher is supposed to return diffrent values for objects that are =
not <b>exactly</b>=C2=A0the same, that&#39;s the whole point of the hasher,=
 and the whole problem of this mutable-wrapper mechanism.</div><div>To defi=
ne a &quot;pseudo-hasher&quot;, that is a function returns equal results on=
ly for equivalent results up to some comparison, by using a real hash of th=
e type is the goal here.</div><div>I wouldn&#39;t have to save the original=
 object if the value is always equivalent, the unordered container insepcts=
 the mutable type with only two functions:</div><div>1. The comparator whic=
h will return the same as if you compared to the original object (since the=
 changed object is equal to the original one).</div><div>2. The hasher whic=
h will always return the hash value of the original object, after it will b=
e saved somewhere (or maybe create a &quot;pseudo-hasher&quot; in some othe=
r way, that has the same effect).</div><div>Therefore, form the containert&=
#39;s perspective the object was never changed, and so does it&#39;s positi=
on in the container. If by accident the hash value of the object was change=
d, the object must be moved, otherwise the container will be broken, using =
this &quot;pseudo-hahser&quot; will stop that from happening.</div><div><br=
></div><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-lef=
t-style: solid; padding-left: 1ex;"><div>I think this is a worthwhile goal,=
 but note that this proposal from two years ago solves that problem and muc=
h more:</div><div><a href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/pa=
pers/2013/n3586.pdf" target=3D"_blank" rel=3D"nofollow" style=3D"cursor: po=
inter;">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3586.pdf</=
a><br></div><div><br></div><div>I&#39;m fond of this approach, it provides =
much needed functionality in the standard library that one would otherwise =
have to resort to boost::intrusive to get (in addition to writing a lot of =
boilerplate).</div></blockquote><div>=C2=A0</div><div>This proposal is inde=
ed much more extensive than the ideas in this thread, however I can&#39;t s=
eem to find information why it was rejected (I assume it was, since this is=
n&#39;t part of the standard library today). Where can I find this informat=
ion?</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&quot; 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_498_455528457.1437041056789--
------=_Part_497_276833959.1437041056788--

.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Thu, 16 Jul 2015 13:11:30 +0300
Raw View
On 16 July 2015 at 13:04, Omer Rosler <omer.rosler@gmail.com> wrote:
>> I think this is a worthwhile goal, but note that this proposal from two
>> years ago solves that problem and much more:
>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3586.pdf
>>
>> I'm fond of this approach, it provides much needed functionality in the
>> standard library that one would otherwise have to resort to boost::intrusive
>> to get (in addition to writing a lot of boilerplate).
> This proposal is indeed much more extensive than the ideas in this thread,
> however I can't seem to find information why it was rejected (I assume it
> was, since this isn't part of the standard library today). Where can I find
> this information?


It wasn't rejected. It was discussed in the Bristol meeting in 2013,
but it didn't
make it into c++14 because the wording wasn't ready. I suppose that proposal
could/should be resurrected.

--

---
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/.

.


Author: "'Edward Catmur' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Thu, 16 Jul 2015 13:52:34 +0100
Raw View
--f46d043bdfa29c1e53051afd8b42
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

On Thu, Jul 16, 2015 at 11:04 AM, Omer Rosler <omer.rosler@gmail.com> wrote=
:

> On Thursday, July 16, 2015 at 12:06:56 PM UTC+3, Edward Catmur wrote:
>>
>> That's why I was looking for an example - I find it difficult to envisag=
e
>> a type that has values equivalent under incomparability or under equalit=
y
>> but with different hashes; if you're having to save the original hash va=
lue
>> then wouldn't you also have to save the entire original value for use wi=
th
>> equality or strict weak comparators?
>>
>> First, hasher is supposed to return diffrent values for objects that are
> not *exactly* the same, that's the whole point of the hasher, and the
> whole problem of this mutable-wrapper mechanism.
>

I think we have a philosophical difference here; to me it's perfectly OK
for a hasher to return the same hash value for distinguishable objects. An
example would be std::hash<double>, which returns the same hash value for
0.0 and -0.0.

To define a "pseudo-hasher", that is a function returns equal results only
> for equivalent results up to some comparison, by using a real hash of the
> type is the goal here.
> I wouldn't have to save the original object if the value is always
> equivalent, the unordered container insepcts the mutable type with only t=
wo
> functions:
> 1. The comparator which will return the same as if you compared to the
> original object (since the changed object is equal to the original one).
>

[unord.hash] requires: [...] if k1 =3D=3D k2 is true, h(k1) =3D=3D h(k2) is=
 also
true, where h is an object of type hash and k1 and k2 are objects of type
Key [...]
Similarly, [unord.req] requires: Two values k1 and k2 of type Key are
considered equivalent if the container=E2=80=99s key equality predicate ret=
urns
true when passed those values. If k1 and k2 are equivalent, the container=
=E2=80=99s
hash function shall return the same value for both. [ Note: Thus, when an
unordered associative container is instantiated with a nondefault Pred
parameter it usually needs a non-default Hash parameter as well. =E2=80=94 =
end note
]

If you're creating a container with an equality comparator and hasher that
don't together respect [unord.req], then I think you have undefined
behavior. If, on the other hand, the comparator and hasher do together
respect [unord.req], then any change to the key that preserves equality
comparison will by necessity leave the hash value unaltered.

2. The hasher which will always return the hash value of the original
> object, after it will be saved somewhere (or maybe create a "pseudo-hashe=
r"
> in some other way, that has the same effect).
> Therefore, form the containert's perspective the object was never changed=
,
> and so does it's position in the container. If by accident the hash value
> of the object was changed, the object must be moved, otherwise the
> container will be broken, using this "pseudo-hahser" will stop that from
> happening.
>

--=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/.

--f46d043bdfa29c1e53051afd8b42
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On T=
hu, Jul 16, 2015 at 11:04 AM, Omer Rosler <span dir=3D"ltr">&lt;<a href=3D"=
mailto:omer.rosler@gmail.com" target=3D"_blank">omer.rosler@gmail.com</a>&g=
t;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px 0=
px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);borde=
r-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><span class=3D"">On T=
hursday, July 16, 2015 at 12:06:56 PM UTC+3, Edward Catmur wrote:<blockquot=
e 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-lef=
t:1ex"><div dir=3D"ltr">That&#39;s why I was looking for an example - I fin=
d it difficult to envisage a type that has values equivalent under incompar=
ability or under equality but with different hashes; if you&#39;re having t=
o save the original hash value then wouldn&#39;t you also have to save the =
entire original value for use with equality or strict weak comparators?<br>=
<br></div></blockquote></span><div>First, hasher is supposed to return diff=
rent values for objects that are not <b>exactly</b>=C2=A0the same, that&#39=
;s the whole point of the hasher, and the whole problem of this mutable-wra=
pper mechanism.</div></div></blockquote><div><br></div><div>I think we have=
 a philosophical difference here; to me it&#39;s perfectly OK for a hasher =
to return the same hash value for distinguishable objects. An example would=
 be std::hash&lt;double&gt;, which returns the same hash value for 0.0 and =
-0.0.</div><div><br></div><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"><div dir=3D"ltr"><div>To define =
a &quot;pseudo-hasher&quot;, that is a function returns equal results only =
for equivalent results up to some comparison, by using a real hash of the t=
ype is the goal here.</div><div>I wouldn&#39;t have to save the original ob=
ject if the value is always equivalent, the unordered container insepcts th=
e mutable type with only two functions:</div><div>1. The comparator which w=
ill return the same as if you compared to the original object (since the ch=
anged object is equal to the original one).</div></div></blockquote><div><b=
r></div><div><div>[unord.hash] requires: [...]=C2=A0if k1 =3D=3D k2 is true=
, h(k1) =3D=3D h(k2) is also true, where h is an object of type hash=C2=A0a=
nd k1 and k2 are objects of type Key=C2=A0[...]</div><div>Similarly, [unord=
..req] requires: Two values k1 and k2 of type Key are considered equivalent =
if the container=E2=80=99s key equality predicate returns
true when passed those values. If k1 and k2 are equivalent, the container=
=E2=80=99s hash function shall return the
same value for both. [ Note: Thus, when an unordered associative container =
is instantiated with a nondefault
Pred parameter it usually needs a non-default Hash parameter as well. =E2=
=80=94 end note ]</div></div><div><br></div><div>If you&#39;re creating a c=
ontainer with an equality comparator and hasher that don&#39;t together res=
pect [unord.req], then I think you have undefined behavior. If, on the othe=
r hand, the comparator and hasher do together respect [unord.req], then any=
 change to the key that preserves equality comparison will by necessity lea=
ve the hash value unaltered.<br></div><div><br></div><blockquote class=3D"g=
mail_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"><div =
dir=3D"ltr"><div>2. The hasher which will always return the hash value of t=
he original object, after it will be saved somewhere (or maybe create a &qu=
ot;pseudo-hasher&quot; in some other way, that has the same effect).</div><=
div>Therefore, form the containert&#39;s perspective the object was never c=
hanged, and so does it&#39;s position in the container. If by accident the =
hash value of the object was changed, the object must be moved, otherwise t=
he container will be broken, using this &quot;pseudo-hahser&quot; will stop=
 that from happening.</div></div></blockquote><div><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&quot; 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 />

--f46d043bdfa29c1e53051afd8b42--

.


Author: "'Edward Catmur' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Thu, 16 Jul 2015 13:57:53 +0100
Raw View
--089e01228c409baf2f051afd9e6b
Content-Type: text/plain; charset=UTF-8

There's an obvious problem with that proposal, specifically with the
motivating example "Changing the key of an element": the value_type of the
key-value containers is std::pair
<http://en.cppreference.com/w/cpp/utility/pair><const Key, T> , so it is
not possible to alter the key even operating on a node_ptr. Do you know
whether this was discussed at Bristol and if so what the resolution was?

On Thu, Jul 16, 2015 at 11:11 AM, Ville Voutilainen <
ville.voutilainen@gmail.com> wrote:

> On 16 July 2015 at 13:04, Omer Rosler <omer.rosler@gmail.com> wrote:
> >> I think this is a worthwhile goal, but note that this proposal from two
> >> years ago solves that problem and much more:
> >> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3586.pdf
> >>
> >> I'm fond of this approach, it provides much needed functionality in the
> >> standard library that one would otherwise have to resort to
> boost::intrusive
> >> to get (in addition to writing a lot of boilerplate).
> > This proposal is indeed much more extensive than the ideas in this
> thread,
> > however I can't seem to find information why it was rejected (I assume it
> > was, since this isn't part of the standard library today). Where can I
> find
> > this information?
>
>
> It wasn't rejected. It was discussed in the Bristol meeting in 2013,
> but it didn't
> make it into c++14 because the wording wasn't ready. I suppose that
> proposal
> could/should be resurrected.
>
> --
>
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/xl9JS25nuuU/unsubscribe
> .
> To unsubscribe from this group and all its topics, 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/.
>

--

---
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/.

--089e01228c409baf2f051afd9e6b
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">There&#39;s an obvious problem with that proposal, specifi=
cally with the motivating example &quot;Changing the key of an element&quot=
;: the value_type of the key-value containers is=C2=A0<a href=3D"http://en.=
cppreference.com/w/cpp/utility/pair" style=3D"text-decoration:none;color:rg=
b(0,48,128);font-family:DejaVuSansMono,&#39;DejaVu Sans Mono&#39;,courier,m=
onospace;font-size:12.8000001907349px;white-space:nowrap;background:none rg=
ba(0,0,0,0.027451)"><span class=3D"">std::<span class=3D"">pair</span></spa=
n></a><span class=3D"" style=3D"color:rgb(0,0,128);font-family:DejaVuSansMo=
no,&#39;DejaVu Sans Mono&#39;,courier,monospace;font-size:12.8000001907349p=
x;white-space:nowrap;background-color:rgba(0,0,0,0.027451)">&lt;</span><spa=
n class=3D"" style=3D"color:rgb(0,0,255);font-family:DejaVuSansMono,&#39;De=
jaVu Sans Mono&#39;,courier,monospace;font-size:12.8000001907349px;white-sp=
ace:nowrap;background-color:rgba(0,0,0,0.027451)">const</span><span style=
=3D"color:rgb(0,0,0);font-family:DejaVuSansMono,&#39;DejaVu Sans Mono&#39;,=
courier,monospace;font-size:12.8000001907349px;white-space:nowrap;backgroun=
d-color:rgba(0,0,0,0.027451)">=C2=A0Key, T</span><span class=3D"" style=3D"=
color:rgb(0,0,128);font-family:DejaVuSansMono,&#39;DejaVu Sans Mono&#39;,co=
urier,monospace;font-size:12.8000001907349px;white-space:nowrap;background-=
color:rgba(0,0,0,0.027451)">&gt;</span>=C2=A0, so it is not possible to alt=
er the key even operating on a node_ptr. Do you know whether this was discu=
ssed at Bristol and if so what the resolution was?</div><div class=3D"gmail=
_extra"><br><div class=3D"gmail_quote">On Thu, Jul 16, 2015 at 11:11 AM, Vi=
lle Voutilainen <span dir=3D"ltr">&lt;<a href=3D"mailto:ville.voutilainen@g=
mail.com" target=3D"_blank">ville.voutilainen@gmail.com</a>&gt;</span> wrot=
e:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-l=
eft:1px #ccc solid;padding-left:1ex"><span class=3D"">On 16 July 2015 at 13=
:04, Omer Rosler &lt;<a href=3D"mailto:omer.rosler@gmail.com">omer.rosler@g=
mail.com</a>&gt; wrote:<br>
&gt;&gt; I think this is a worthwhile goal, but note that this proposal fro=
m two<br>
&gt;&gt; years ago solves that problem and much more:<br>
&gt;&gt; <a href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013=
/n3586.pdf" rel=3D"noreferrer" target=3D"_blank">http://www.open-std.org/jt=
c1/sc22/wg21/docs/papers/2013/n3586.pdf</a><br>
&gt;&gt;<br>
</span><span class=3D"">&gt;&gt; I&#39;m fond of this approach, it provides=
 much needed functionality in the<br>
&gt;&gt; standard library that one would otherwise have to resort to boost:=
:intrusive<br>
&gt;&gt; to get (in addition to writing a lot of boilerplate).<br>
&gt; This proposal is indeed much more extensive than the ideas in this thr=
ead,<br>
&gt; however I can&#39;t seem to find information why it was rejected (I as=
sume it<br>
&gt; was, since this isn&#39;t part of the standard library today). Where c=
an I find<br>
&gt; this information?<br>
<br>
<br>
</span>It wasn&#39;t rejected. It was discussed in the Bristol meeting in 2=
013,<br>
but it didn&#39;t<br>
make it into c++14 because the wording wasn&#39;t ready. I suppose that pro=
posal<br>
could/should be resurrected.<br>
<span class=3D""><br>
--<br>
<br>
---<br>
You received this message because you are subscribed to a topic in the Goog=
le Groups &quot;ISO C++ Standard - Future Proposals&quot; group.<br>
</span>To unsubscribe from this topic, visit <a href=3D"https://groups.goog=
le.com/a/isocpp.org/d/topic/std-proposals/xl9JS25nuuU/unsubscribe" rel=3D"n=
oreferrer" target=3D"_blank">https://groups.google.com/a/isocpp.org/d/topic=
/std-proposals/xl9JS25nuuU/unsubscribe</a>.<br>
To unsubscribe from this group and all its topics, send an email to <a href=
=3D"mailto:std-proposals%2Bunsubscribe@isocpp.org">std-proposals+unsubscrib=
e@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/" rel=3D"noreferrer" target=3D"_blank">http://groups.google.c=
om/a/isocpp.org/group/std-proposals/</a>.<br>
</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&quot; 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 />

--089e01228c409baf2f051afd9e6b--

.


Author: Miro Knejp <miro.knejp@gmail.com>
Date: Thu, 16 Jul 2015 15:01:23 +0200
Raw View
--Apple-Mail=_1B30A16B-A23F-479C-BA32-72E9959A8434
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8


> On 16 Jul 2015, at 14:52 , 'Edward Catmur' via ISO C++ Standard - Future =
Proposals <std-proposals@isocpp.org> wrote:
>=20
> On Thu, Jul 16, 2015 at 11:04 AM, Omer Rosler <omer.rosler@gmail.com <mai=
lto:omer.rosler@gmail.com>> wrote:
> On Thursday, July 16, 2015 at 12:06:56 PM UTC+3, Edward Catmur wrote:
> That's why I was looking for an example - I find it difficult to envisage=
 a type that has values equivalent under incomparability or under equality =
but with different hashes; if you're having to save the original hash value=
 then wouldn't you also have to save the entire original value for use with=
 equality or strict weak comparators?
>=20
> First, hasher is supposed to return diffrent values for objects that are =
not exactly the same, that's the whole point of the hasher, and the whole p=
roblem of this mutable-wrapper mechanism.
>=20
> I think we have a philosophical difference here; to me it's perfectly OK =
for a hasher to return the same hash value for distinguishable objects. An =
example would be std::hash<double>, which returns the same hash value for 0=
..0 and -0.0.

0.0 and -0.0 compare equal, see https://en.wikipedia.org/wiki/Signed_zero#C=
omparisons <https://en.wikipedia.org/wiki/Signed_zero>

--=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/.

--Apple-Mail=_1B30A16B-A23F-479C-BA32-72E9959A8434
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8

<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dus-ascii"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode=
: space; -webkit-line-break: after-white-space;" class=3D""><br class=3D"">=
<div><blockquote type=3D"cite" class=3D""><div class=3D"">On 16 Jul 2015, a=
t 14:52 , 'Edward Catmur' via ISO C++ Standard - Future Proposals &lt;<a hr=
ef=3D"mailto:std-proposals@isocpp.org" class=3D"">std-proposals@isocpp.org<=
/a>&gt; wrote:</div><br class=3D"Apple-interchange-newline"><div class=3D""=
><div dir=3D"ltr" class=3D""><div class=3D"gmail_extra"><div class=3D"gmail=
_quote">On Thu, Jul 16, 2015 at 11:04 AM, Omer Rosler <span dir=3D"ltr" cla=
ss=3D"">&lt;<a href=3D"mailto:omer.rosler@gmail.com" target=3D"_blank" clas=
s=3D"">omer.rosler@gmail.com</a>&gt;</span> wrote:<br class=3D""><blockquot=
e 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-lef=
t:1ex"><div dir=3D"ltr" class=3D""><span class=3D"">On Thursday, July 16, 2=
015 at 12:06:56 PM UTC+3, Edward Catmur wrote:<blockquote class=3D"gmail_qu=
ote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-co=
lor:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"=
ltr" class=3D"">That's why I was looking for an example - I find it difficu=
lt to envisage a type that has values equivalent under incomparability or u=
nder equality but with different hashes; if you're having to save the origi=
nal hash value then wouldn't you also have to save the entire original valu=
e for use with equality or strict weak comparators?<br class=3D""><br class=
=3D""></div></blockquote></span><div class=3D"">First, hasher is supposed t=
o return diffrent values for objects that are not <b class=3D"">exactly</b>=
&nbsp;the same, that's the whole point of the hasher, and the whole problem=
 of this mutable-wrapper mechanism.</div></div></blockquote><div class=3D""=
><br class=3D""></div><div class=3D"">I think we have a philosophical diffe=
rence here; to me it's perfectly OK for a hasher to return the same hash va=
lue for distinguishable objects. An example would be std::hash&lt;double&gt=
;, which returns the same hash value for 0.0 and -0.0.</div></div></div></d=
iv></div></blockquote><div><br class=3D""></div>0.0 and -0.0 compare equal,=
 see&nbsp;<a href=3D"https://en.wikipedia.org/wiki/Signed_zero" class=3D"">=
https://en.wikipedia.org/wiki/Signed_zero#Comparisons</a></div></body></htm=
l>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; 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 />

--Apple-Mail=_1B30A16B-A23F-479C-BA32-72E9959A8434--

.


Author: "'Edward Catmur' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Thu, 16 Jul 2015 14:04:53 +0100
Raw View
--f46d043bdfa2a8544c051afdb733
Content-Type: text/plain; charset=UTF-8

On Thu, Jul 16, 2015 at 2:01 PM, Miro Knejp <miro.knejp@gmail.com> wrote:

> On 16 Jul 2015, at 14:52 , 'Edward Catmur' via ISO C++ Standard - Future
> Proposals <std-proposals@isocpp.org> wrote:
>
> On Thu, Jul 16, 2015 at 11:04 AM, Omer Rosler <omer.rosler@gmail.com>
> wrote:
>
>> On Thursday, July 16, 2015 at 12:06:56 PM UTC+3, Edward Catmur wrote:
>>>
>>> That's why I was looking for an example - I find it difficult to
>>> envisage a type that has values equivalent under incomparability or under
>>> equality but with different hashes; if you're having to save the original
>>> hash value then wouldn't you also have to save the entire original value
>>> for use with equality or strict weak comparators?
>>>
>>> First, hasher is supposed to return diffrent values for objects that are
>> not *exactly* the same, that's the whole point of the hasher, and the
>> whole problem of this mutable-wrapper mechanism.
>>
>
> I think we have a philosophical difference here; to me it's perfectly OK
> for a hasher to return the same hash value for distinguishable objects. An
> example would be std::hash<double>, which returns the same hash value for
> 0.0 and -0.0.
>
>
> 0.0 and -0.0 compare equal, see
> https://en.wikipedia.org/wiki/Signed_zero#Comparisons
> <https://en.wikipedia.org/wiki/Signed_zero>
>

Well, sure.  They're still distinguishable i.e. not exactly the same.
(Think signbit, or division, or indeed I/O.)

--

---
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/.

--f46d043bdfa2a8544c051afdb733
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On T=
hu, Jul 16, 2015 at 2:01 PM, Miro Knejp <span dir=3D"ltr">&lt;<a href=3D"ma=
ilto:miro.knejp@gmail.com" target=3D"_blank">miro.knejp@gmail.com</a>&gt;</=
span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8e=
x;border-left:1px #ccc solid;padding-left:1ex"><div style=3D"word-wrap:brea=
k-word"><div><blockquote type=3D"cite"><div>On 16 Jul 2015, at 14:52 , &#39=
;Edward Catmur&#39; via ISO C++ Standard - Future Proposals &lt;<a href=3D"=
mailto:std-proposals@isocpp.org" target=3D"_blank">std-proposals@isocpp.org=
</a>&gt; wrote:</div><br><div><div dir=3D"ltr"><div class=3D"gmail_extra"><=
div class=3D"gmail_quote">On Thu, Jul 16, 2015 at 11:04 AM, Omer Rosler <sp=
an dir=3D"ltr">&lt;<a href=3D"mailto:omer.rosler@gmail.com" target=3D"_blan=
k">omer.rosler@gmail.com</a>&gt;</span> wrote:<br><blockquote class=3D"gmai=
l_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-lef=
t-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=
=3D"ltr"><span>On Thursday, July 16, 2015 at 12:06:56 PM UTC+3, Edward Catm=
ur wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8e=
x;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-styl=
e:solid;padding-left:1ex"><div dir=3D"ltr">That&#39;s why I was looking for=
 an example - I find it difficult to envisage a type that has values equiva=
lent under incomparability or under equality but with different hashes; if =
you&#39;re having to save the original hash value then wouldn&#39;t you als=
o have to save the entire original value for use with equality or strict we=
ak comparators?<br><br></div></blockquote></span><div>First, hasher is supp=
osed to return diffrent values for objects that are not <b>exactly</b>=C2=
=A0the same, that&#39;s the whole point of the hasher, and the whole proble=
m of this mutable-wrapper mechanism.</div></div></blockquote><div><br></div=
><div>I think we have a philosophical difference here; to me it&#39;s perfe=
ctly OK for a hasher to return the same hash value for distinguishable obje=
cts. An example would be std::hash&lt;double&gt;, which returns the same ha=
sh value for 0.0 and -0.0.</div></div></div></div></div></blockquote><div><=
br></div>0.0 and -0.0 compare equal, see=C2=A0<a href=3D"https://en.wikiped=
ia.org/wiki/Signed_zero" target=3D"_blank">https://en.wikipedia.org/wiki/Si=
gned_zero#Comparisons</a></div></div></blockquote><div><br></div><div>Well,=
 sure.=C2=A0 They&#39;re still distinguishable i.e. not exactly the same. (=
Think signbit, or division, or indeed I/O.)</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&quot; 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 />

--f46d043bdfa2a8544c051afdb733--

.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Thu, 16 Jul 2015 16:06:17 +0300
Raw View
On 16 July 2015 at 15:57, 'Edward Catmur' via ISO C++ Standard -
Future Proposals <std-proposals@isocpp.org> wrote:
> There's an obvious problem with that proposal, specifically with the
> motivating example "Changing the key of an element": the value_type of the
> key-value containers is std::pair<const Key, T> , so it is not possible to
> alter the key even operating on a node_ptr. Do you know whether this was
> discussed at Bristol and if so what the resolution was?


I see fragments of such a discussion, but nothing very
concrete/conclusive. There is a mention
that the constness of the key in value_type can't be changed, because
that would "break
the world", but I don't see much discussion about that example. I
expect that point would be
re-discussed if the proposal is resurrected.

--

---
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/.

.


Author: Jeremy Maitin-Shepard <jeremy@jeremyms.com>
Date: Fri, 17 Jul 2015 10:47:59 -0700 (PDT)
Raw View
------=_Part_2627_1412203630.1437155279959
Content-Type: multipart/alternative;
 boundary="----=_Part_2628_888754892.1437155279959"

------=_Part_2628_888754892.1437155279959
Content-Type: text/plain; charset=UTF-8

What about the simple solution of leaving the value_type as pair<const Key,
T> but explicitly stating that const_casting the first member to Key & is
permitted, as are modifications, provided that the value is equivalent
under the comparison function/hash?

On Thursday, July 16, 2015 at 6:06:21 AM UTC-7, Ville Voutilainen wrote:
>
> On 16 July 2015 at 15:57, 'Edward Catmur' via ISO C++ Standard -
> Future Proposals <std-pr...@isocpp.org <javascript:>> wrote:
> > There's an obvious problem with that proposal, specifically with the
> > motivating example "Changing the key of an element": the value_type of
> the
> > key-value containers is std::pair<const Key, T> , so it is not possible
> to
> > alter the key even operating on a node_ptr. Do you know whether this was
> > discussed at Bristol and if so what the resolution was?
>
>
> I see fragments of such a discussion, but nothing very
> concrete/conclusive. There is a mention
> that the constness of the key in value_type can't be changed, because
> that would "break
> the world", but I don't see much discussion about that example. I
> expect that point would be
> re-discussed if the proposal is resurrected.
>

--

---
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_2628_888754892.1437155279959
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">What about the simple solution of leaving the value_type a=
s pair&lt;const Key, T&gt; but explicitly stating that const_casting the fi=
rst member to Key &amp; is permitted, as are modifications, provided that t=
he value is equivalent under the comparison function/hash?<br><br>On Thursd=
ay, July 16, 2015 at 6:06:21 AM UTC-7, Ville Voutilainen wrote:<blockquote =
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1p=
x #ccc solid;padding-left: 1ex;">On 16 July 2015 at 15:57, &#39;Edward Catm=
ur&#39; via ISO C++ Standard -
<br>Future Proposals &lt;<a href=3D"javascript:" target=3D"_blank" rel=3D"n=
ofollow" onmousedown=3D"this.href=3D&#39;javascript:&#39;;return true;" onc=
lick=3D"this.href=3D&#39;javascript:&#39;;return true;">std-pr...@isocpp.or=
g</a>&gt; wrote:
<br>&gt; There&#39;s an obvious problem with that proposal, specifically wi=
th the
<br>&gt; motivating example &quot;Changing the key of an element&quot;: the=
 value_type of the
<br>&gt; key-value containers is std::pair&lt;const Key, T&gt; , so it is n=
ot possible to
<br>&gt; alter the key even operating on a node_ptr. Do you know whether th=
is was
<br>&gt; discussed at Bristol and if so what the resolution was?
<br>
<br>
<br>I see fragments of such a discussion, but nothing very
<br>concrete/conclusive. There is a mention
<br>that the constness of the key in value_type can&#39;t be changed, becau=
se
<br>that would &quot;break
<br>the world&quot;, but I don&#39;t see much discussion about that example=
.. I
<br>expect that point would be
<br>re-discussed if the proposal is resurrected.
<br></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&quot; 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_2628_888754892.1437155279959--
------=_Part_2627_1412203630.1437155279959--

.


Author: Edward Catmur <ed@catmur.co.uk>
Date: Fri, 17 Jul 2015 10:59:02 -0700 (PDT)
Raw View
------=_Part_2266_274128417.1437155942238
Content-Type: multipart/alternative;
 boundary="----=_Part_2267_646308427.1437155942238"

------=_Part_2267_646308427.1437155942238
Content-Type: text/plain; charset=UTF-8

That wouldn't work; the data member first of pair<Key const, T> is an
object of type Key const and the language guarantees that such an object is
not modified (rather, that casting away its constness is UB)
([dcl.type.cv]/4).

On Friday, 17 July 2015 18:48:00 UTC+1, Jeremy Maitin-Shepard wrote:
>
> What about the simple solution of leaving the value_type as pair<const
> Key, T> but explicitly stating that const_casting the first member to Key &
> is permitted, as are modifications, provided that the value is equivalent
> under the comparison function/hash?
>
> On Thursday, July 16, 2015 at 6:06:21 AM UTC-7, Ville Voutilainen wrote:
>>
>> On 16 July 2015 at 15:57, 'Edward Catmur' via ISO C++ Standard -
>> Future Proposals <std-pr...@isocpp.org> wrote:
>> > There's an obvious problem with that proposal, specifically with the
>> > motivating example "Changing the key of an element": the value_type of
>> the
>> > key-value containers is std::pair<const Key, T> , so it is not possible
>> to
>> > alter the key even operating on a node_ptr. Do you know whether this
>> was
>> > discussed at Bristol and if so what the resolution was?
>>
>>
>> I see fragments of such a discussion, but nothing very
>> concrete/conclusive. There is a mention
>> that the constness of the key in value_type can't be changed, because
>> that would "break
>> the world", but I don't see much discussion about that example. I
>> expect that point would be
>> re-discussed if the proposal is resurrected.
>>
>

--

---
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_2267_646308427.1437155942238
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">That wouldn&#39;t work; the data member first of=C2=A0pair=
&lt;Key const, T&gt; is an object of type Key const=C2=A0and the language g=
uarantees that such an object is not modified (rather, that casting away it=
s constness is UB) ([dcl.type.cv]/4).<div><br></div><div>On Friday, 17 July=
 2015 18:48:00 UTC+1, Jeremy Maitin-Shepard  wrote:<blockquote class=3D"gma=
il_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid=
;padding-left: 1ex;"><div dir=3D"ltr">What about the simple solution of lea=
ving the value_type as pair&lt;const Key, T&gt; but explicitly stating that=
 const_casting the first member to Key &amp; is permitted, as are modificat=
ions, provided that the value is equivalent under the comparison function/h=
ash?<br><br>On Thursday, July 16, 2015 at 6:06:21 AM UTC-7, Ville Voutilain=
en wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.=
8ex;border-left:1px #ccc solid;padding-left:1ex">On 16 July 2015 at 15:57, =
&#39;Edward Catmur&#39; via ISO C++ Standard -
<br>Future Proposals &lt;<a rel=3D"nofollow">std-pr...@isocpp.org</a>&gt; w=
rote:
<br>&gt; There&#39;s an obvious problem with that proposal, specifically wi=
th the
<br>&gt; motivating example &quot;Changing the key of an element&quot;: the=
 value_type of the
<br>&gt; key-value containers is std::pair&lt;const Key, T&gt; , so it is n=
ot possible to
<br>&gt; alter the key even operating on a node_ptr. Do you know whether th=
is was
<br>&gt; discussed at Bristol and if so what the resolution was?
<br>
<br>
<br>I see fragments of such a discussion, but nothing very
<br>concrete/conclusive. There is a mention
<br>that the constness of the key in value_type can&#39;t be changed, becau=
se
<br>that would &quot;break
<br>the world&quot;, but I don&#39;t see much discussion about that example=
.. I
<br>expect that point would be
<br>re-discussed if the proposal is resurrected.
<br></blockquote></div></blockquote></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&quot; 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_2267_646308427.1437155942238--
------=_Part_2266_274128417.1437155942238--

.


Author: Edward Catmur <ed@catmur.co.uk>
Date: Fri, 17 Jul 2015 11:05:26 -0700 (PDT)
Raw View
------=_Part_2286_524523289.1437156326370
Content-Type: multipart/alternative;
 boundary="----=_Part_2287_1067920163.1437156326370"

------=_Part_2287_1067920163.1437156326370
Content-Type: text/plain; charset=UTF-8

Also, the container couldn't destroy and renew the value because of
[basic.life]/7 -
see http://stackoverflow.com/questions/7586848/placement-new-breaks-consts-and-references

The constness of the key is great for optimization but that makes it tricky
to mutate it - IMO that indicates that making mutation possible should be
opt-in rather than available by default; otherwise we'd have a rarely-used
feature (key mutation) pessimizing code generation in the general case.

On Friday, 17 July 2015 18:59:02 UTC+1, Edward Catmur wrote:
>
> That wouldn't work; the data member first of pair<Key const, T> is an
> object of type Key const and the language guarantees that such an object is
> not modified (rather, that casting away its constness is UB) ([dcl.type.cv
> ]/4).
>
> On Friday, 17 July 2015 18:48:00 UTC+1, Jeremy Maitin-Shepard wrote:
>>
>> What about the simple solution of leaving the value_type as pair<const
>> Key, T> but explicitly stating that const_casting the first member to Key &
>> is permitted, as are modifications, provided that the value is equivalent
>> under the comparison function/hash?
>>
>> On Thursday, July 16, 2015 at 6:06:21 AM UTC-7, Ville Voutilainen wrote:
>>>
>>> On 16 July 2015 at 15:57, 'Edward Catmur' via ISO C++ Standard -
>>> Future Proposals <std-pr...@isocpp.org> wrote:
>>> > There's an obvious problem with that proposal, specifically with the
>>> > motivating example "Changing the key of an element": the value_type of
>>> the
>>> > key-value containers is std::pair<const Key, T> , so it is not
>>> possible to
>>> > alter the key even operating on a node_ptr. Do you know whether this
>>> was
>>> > discussed at Bristol and if so what the resolution was?
>>>
>>>
>>> I see fragments of such a discussion, but nothing very
>>> concrete/conclusive. There is a mention
>>> that the constness of the key in value_type can't be changed, because
>>> that would "break
>>> the world", but I don't see much discussion about that example. I
>>> expect that point would be
>>> re-discussed if the proposal is resurrected.
>>>
>>

--

---
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_2287_1067920163.1437156326370
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Also, the container couldn&#39;t destroy and renew the val=
ue because of=C2=A0 [basic.life]/7 - see=C2=A0http://stackoverflow.com/ques=
tions/7586848/placement-new-breaks-consts-and-references<div><br></div><div=
>The constness of the key is great for optimization but that makes it trick=
y to mutate it - IMO that indicates that making mutation possible should be=
 opt-in rather than available by default; otherwise we&#39;d have a rarely-=
used feature (key mutation) pessimizing code generation in the general case=
..<br><br>On Friday, 17 July 2015 18:59:02 UTC+1, Edward Catmur  wrote:<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">That wouldn&#39;t =
work; the data member first of=C2=A0pair&lt;Key const, T&gt; is an object o=
f type Key const=C2=A0and the language guarantees that such an object is no=
t modified (rather, that casting away its constness is UB) ([<a href=3D"htt=
p://dcl.type.cv" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.hre=
f=3D&#39;http://www.google.com/url?q\75http%3A%2F%2Fdcl.type.cv\46sa\75D\46=
sntz\0751\46usg\75AFQjCNHfRFG-haOKUQotwT009AEJNE7QIQ&#39;;return true;" onc=
lick=3D"this.href=3D&#39;http://www.google.com/url?q\75http%3A%2F%2Fdcl.typ=
e.cv\46sa\75D\46sntz\0751\46usg\75AFQjCNHfRFG-haOKUQotwT009AEJNE7QIQ&#39;;r=
eturn true;">dcl.type.cv</a>]/4).<div><br></div><div>On Friday, 17 July 201=
5 18:48:00 UTC+1, Jeremy Maitin-Shepard  wrote:<blockquote class=3D"gmail_q=
uote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;paddin=
g-left:1ex"><div dir=3D"ltr">What about the simple solution of leaving the =
value_type as pair&lt;const Key, T&gt; but explicitly stating that const_ca=
sting the first member to Key &amp; is permitted, as are modifications, pro=
vided that the value is equivalent under the comparison function/hash?<br><=
br>On Thursday, July 16, 2015 at 6:06:21 AM UTC-7, Ville Voutilainen wrote:=
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;borde=
r-left:1px #ccc solid;padding-left:1ex">On 16 July 2015 at 15:57, &#39;Edwa=
rd Catmur&#39; via ISO C++ Standard -
<br>Future Proposals &lt;<a rel=3D"nofollow">std-pr...@isocpp.org</a>&gt; w=
rote:
<br>&gt; There&#39;s an obvious problem with that proposal, specifically wi=
th the
<br>&gt; motivating example &quot;Changing the key of an element&quot;: the=
 value_type of the
<br>&gt; key-value containers is std::pair&lt;const Key, T&gt; , so it is n=
ot possible to
<br>&gt; alter the key even operating on a node_ptr. Do you know whether th=
is was
<br>&gt; discussed at Bristol and if so what the resolution was?
<br>
<br>
<br>I see fragments of such a discussion, but nothing very
<br>concrete/conclusive. There is a mention
<br>that the constness of the key in value_type can&#39;t be changed, becau=
se
<br>that would &quot;break
<br>the world&quot;, but I don&#39;t see much discussion about that example=
.. I
<br>expect that point would be
<br>re-discussed if the proposal is resurrected.
<br></blockquote></div></blockquote></div></div></blockquote></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&quot; 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_2287_1067920163.1437156326370--
------=_Part_2286_524523289.1437156326370--

.


Author: Magnus Fromreide <magfr@lysator.liu.se>
Date: Sat, 18 Jul 2015 00:40:46 +0200
Raw View
On Fri, Jul 17, 2015 at 11:05:26AM -0700, Edward Catmur wrote:
> Also, the container couldn't destroy and renew the value because of
> [basic.life]/7 -
> see http://stackoverflow.com/questions/7586848/placement-new-breaks-consts-and-references
>
> The constness of the key is great for optimization but that makes it tricky
> to mutate it - IMO that indicates that making mutation possible should be
> opt-in rather than available by default; otherwise we'd have a rarely-used
> feature (key mutation) pessimizing code generation in the general case.

Isn't this yet another indication of std::tree needing to be standardized?
With std::tree the user is free to choose to supply a container that have a
mutable key.

std::tree also allows the user to simply access the key from the value object
sine it becimes one object instead of the forced two ones we have today.

Now, if the key is mutable and the user mutates it in such a way that the
container requirements fail to be fulfilled afterwards, then the user have
blown off their feet.

Is this container dangerous? Yes. Is it useful? I would say it is despite
it's dangers, now where is my foot cannon?

/MF

--

---
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/.

.


Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
Date: Fri, 17 Jul 2015 16:03:45 -0700 (PDT)
Raw View
------=_Part_2786_332117398.1437174225597
Content-Type: multipart/alternative;
 boundary="----=_Part_2787_717884979.1437174225598"

------=_Part_2787_717884979.1437174225598
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

The constness of const T where T is a user-controlled template parameter is=
=20
never a problem, as far as I'm aware.
This is because C++ allows us to do things like

template<class T>
struct mutable_wrapper {
    mutable T value;
    operator T&() const { return value; }
};

Here's some code showing how to make a std::map with "mutable" keys.
http://melpon.org/wandbox/permlink/Ejs8TvlC79OQObMM

Now, does this kind of code break the invariants of std::map and invoke=20
undefined behavior *that* way? Yes, definitely!
But is there any undefined behavior here as far as accessing a const object=
=20
as non-const, or dangerous casting, or thread-safety concerns? No,=20
definitely not.

To put it another way: If I'd taken a little more time to implement a=20
custom operator< and to ensure that I was modifying the keys only in ways=
=20
that didn't change the sort order of the objects currently being used as=20
map keys, then I contend that there wouldn't be any undefined behavior at=
=20
all.
Of course I'd be happy to be proven wrong...

=E2=80=93Arthur


On Friday, July 17, 2015 at 11:05:26 AM UTC-7, Edward Catmur wrote:
>
> Also, the container couldn't destroy and renew the value because of =20
> [basic.life]/7 - see=20
> http://stackoverflow.com/questions/7586848/placement-new-breaks-consts-an=
d-references
>
> The constness of the key is great for optimization but that makes it=20
> tricky to mutate it - IMO that indicates that making mutation possible=20
> should be opt-in rather than available by default; otherwise we'd have a=
=20
> rarely-used feature (key mutation) pessimizing code generation in the=20
> general case.
>
> On Friday, 17 July 2015 18:59:02 UTC+1, Edward Catmur wrote:
>>
>> That wouldn't work; the data member first of pair<Key const, T> is an=20
>> object of type Key const and the language guarantees that such an object=
 is=20
>> not modified (rather, that casting away its constness is UB) ([
>> dcl.type.cv]/4).
>>
>> On Friday, 17 July 2015 18:48:00 UTC+1, Jeremy Maitin-Shepard wrote:
>>>
>>> What about the simple solution of leaving the value_type as pair<const=
=20
>>> Key, T> but explicitly stating that const_casting the first member to K=
ey &=20
>>> is permitted, as are modifications, provided that the value is equivale=
nt=20
>>> under the comparison function/hash?
>>>
>>> On Thursday, July 16, 2015 at 6:06:21 AM UTC-7, Ville Voutilainen wrote=
:
>>>>
>>>> On 16 July 2015 at 15:57, 'Edward Catmur' via ISO C++ Standard -=20
>>>> Future Proposals <std-pr...@isocpp.org> wrote:=20
>>>> > There's an obvious problem with that proposal, specifically with the=
=20
>>>> > motivating example "Changing the key of an element": the value_type=
=20
>>>> of the=20
>>>> > key-value containers is std::pair<const Key, T> , so it is not=20
>>>> possible to=20
>>>> > alter the key even operating on a node_ptr. Do you know whether this=
=20
>>>> was=20
>>>> > discussed at Bristol and if so what the resolution was?=20
>>>>
>>>>
>>>> I see fragments of such a discussion, but nothing very=20
>>>> concrete/conclusive. There is a mention=20
>>>> that the constness of the key in value_type can't be changed, because=
=20
>>>> that would "break=20
>>>> the world", but I don't see much discussion about that example. I=20
>>>> expect that point would be=20
>>>> re-discussed if the proposal is resurrected.=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_2787_717884979.1437174225598
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">The constness of <font face=3D"courier new, monospace">con=
st T</font>=C2=A0where <font face=3D"courier new, monospace">T</font> is a =
user-controlled template parameter is never a problem, as far as I&#39;m aw=
are.<div>This is because C++ allows us to do things like</div><div><br></di=
v><div><div class=3D"prettyprint" style=3D"background-color: rgb(250, 250, =
250); border: 1px solid rgb(187, 187, 187); word-wrap: break-word;"><code c=
lass=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #0=
08;" class=3D"styled-by-prettify">template</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">class</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> T</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">&gt;</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>struct</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> mu=
table_wrapper </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">mutable</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> T value</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0=
 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">op=
erator</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> T</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">&amp;()</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">const</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: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">return</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> value</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: #660;" class=3D"styled-by-prettify">}</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">};</span></div></code=
></div><div><br></div></div><div>Here&#39;s some code showing how to make a=
 <font face=3D"courier new, monospace">std::map</font> with &quot;mutable&q=
uot; keys.</div><div><a href=3D"http://melpon.org/wandbox/permlink/Ejs8TvlC=
79OQObMM">http://melpon.org/wandbox/permlink/Ejs8TvlC79OQObMM</a><br></div>=
<div><br></div><div>Now, does this kind of code break the invariants of <fo=
nt face=3D"courier new, monospace">std::map</font> and invoke undefined beh=
avior <i>that</i> way? Yes, definitely!</div><div>But is there any undefine=
d behavior here as far as accessing a const object as non-const, or dangero=
us casting, or thread-safety concerns? No, definitely not.</div><div><br></=
div><div>To put it another way: If I&#39;d taken a little more time to impl=
ement a custom <font face=3D"courier new, monospace">operator&lt;</font> an=
d to ensure that I was modifying the keys only in ways that didn&#39;t chan=
ge the sort order of the objects currently being used as map keys, then I c=
ontend that there wouldn&#39;t be any undefined behavior at all.</div><div>=
Of course I&#39;d be happy to be proven wrong...</div><div><br></div><div>=
=E2=80=93Arthur</div><div><br><br>On Friday, July 17, 2015 at 11:05:26 AM U=
TC-7, Edward Catmur 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">Also, the container couldn&#39;t destroy and renew the value b=
ecause of=C2=A0 [basic.life]/7 - see=C2=A0<a href=3D"http://stackoverflow.c=
om/questions/7586848/placement-new-breaks-consts-and-references" target=3D"=
_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D&#39;http://www.google.=
com/url?q\75http%3A%2F%2Fstackoverflow.com%2Fquestions%2F7586848%2Fplacemen=
t-new-breaks-consts-and-references\46sa\75D\46sntz\0751\46usg\75AFQjCNE1K8k=
qiBU6C4iThDsgvLuWgqsz5A&#39;;return true;" onclick=3D"this.href=3D&#39;http=
://www.google.com/url?q\75http%3A%2F%2Fstackoverflow.com%2Fquestions%2F7586=
848%2Fplacement-new-breaks-consts-and-references\46sa\75D\46sntz\0751\46usg=
\75AFQjCNE1K8kqiBU6C4iThDsgvLuWgqsz5A&#39;;return true;">http://stackoverfl=
ow.com/questions/7586848/placement-new-breaks-consts-and-references</a><div=
><br></div><div>The constness of the key is great for optimization but that=
 makes it tricky to mutate it - IMO that indicates that making mutation pos=
sible should be opt-in rather than available by default; otherwise we&#39;d=
 have a rarely-used feature (key mutation) pessimizing code generation in t=
he general case.<br><br>On Friday, 17 July 2015 18:59:02 UTC+1, Edward Catm=
ur  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">That wou=
ldn&#39;t work; the data member first of=C2=A0pair&lt;Key const, T&gt; is a=
n object of type Key const=C2=A0and the language guarantees that such an ob=
ject is not modified (rather, that casting away its constness is UB) ([<a h=
ref=3D"http://dcl.type.cv" rel=3D"nofollow" target=3D"_blank" onmousedown=
=3D"this.href=3D&#39;http://www.google.com/url?q\75http%3A%2F%2Fdcl.type.cv=
\46sa\75D\46sntz\0751\46usg\75AFQjCNHfRFG-haOKUQotwT009AEJNE7QIQ&#39;;retur=
n true;" onclick=3D"this.href=3D&#39;http://www.google.com/url?q\75http%3A%=
2F%2Fdcl.type.cv\46sa\75D\46sntz\0751\46usg\75AFQjCNHfRFG-haOKUQotwT009AEJN=
E7QIQ&#39;;return true;">dcl.type.cv</a>]/4).<div><br></div><div>On Friday,=
 17 July 2015 18:48:00 UTC+1, Jeremy Maitin-Shepard  wrote:<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">What about the simple solution of =
leaving the value_type as pair&lt;const Key, T&gt; but explicitly stating t=
hat const_casting the first member to Key &amp; is permitted, as are modifi=
cations, provided that the value is equivalent under the comparison functio=
n/hash?<br><br>On Thursday, July 16, 2015 at 6:06:21 AM UTC-7, Ville Voutil=
ainen wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left=
:0.8ex;border-left:1px #ccc solid;padding-left:1ex">On 16 July 2015 at 15:5=
7, &#39;Edward Catmur&#39; via ISO C++ Standard -
<br>Future Proposals &lt;<a rel=3D"nofollow">std-pr...@isocpp.org</a>&gt; w=
rote:
<br>&gt; There&#39;s an obvious problem with that proposal, specifically wi=
th the
<br>&gt; motivating example &quot;Changing the key of an element&quot;: the=
 value_type of the
<br>&gt; key-value containers is std::pair&lt;const Key, T&gt; , so it is n=
ot possible to
<br>&gt; alter the key even operating on a node_ptr. Do you know whether th=
is was
<br>&gt; discussed at Bristol and if so what the resolution was?
<br>
<br>
<br>I see fragments of such a discussion, but nothing very
<br>concrete/conclusive. There is a mention
<br>that the constness of the key in value_type can&#39;t be changed, becau=
se
<br>that would &quot;break
<br>the world&quot;, but I don&#39;t see much discussion about that example=
.. I
<br>expect that point would be
<br>re-discussed if the proposal is resurrected.
<br></blockquote></div></blockquote></div></div></blockquote></div></div></=
blockquote></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&quot; 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_2787_717884979.1437174225598--
------=_Part_2786_332117398.1437174225597--

.


Author: Edward Catmur <ed@catmur.co.uk>
Date: Sun, 19 Jul 2015 00:09:09 -0700 (PDT)
Raw View
------=_Part_3373_720779445.1437289749699
Content-Type: text/plain; charset=UTF-8

Right; I posted an example of how to implement comparator checking on a mutable key type above. Mutable keys are absolutely fine as long as the comparator and/or hasher behave correctly.

Specifying a mutable key is one possible opt-in mechanism; another mechanism would be a policy to suppress the addition of const to the key type, or indeed to override the value_type to something other than the default.

--

---
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_3373_720779445.1437289749699--

.


Author: Edward Catmur <ed@catmur.co.uk>
Date: Sun, 19 Jul 2015 00:10:42 -0700 (PDT)
Raw View
------=_Part_10_908996095.1437289842741
Content-Type: text/plain; charset=UTF-8

What's the difference between std::tree and std::set with a non-const value_type?

--

---
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_10_908996095.1437289842741--

.


Author: Magnus Fromreide <magfr@lysator.liu.se>
Date: Sun, 19 Jul 2015 18:17:46 +0200
Raw View
On Sun, Jul 19, 2015 at 12:10:42AM -0700, Edward Catmur wrote:
> What's the difference between std::tree and std::set with a non-const value_type?

tree allows you to specify how the value_type should be converted to the
key_type and doesn't force key_type to be equal to value_type.

template <class T, class C, class A>
using set<T, C, A> = tree<T, T, C, identity, A>;

template <class K, class V, class C, class A>
using map<K, V, A> = tree<pair<const K, V>, C, select1st, A>;

tree was in stlport back in the days, but it isn't part of std.

/MF

--

---
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/.

.


Author: "'Edward Catmur' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Mon, 20 Jul 2015 00:35:59 +0100
Raw View
--047d7bb042722d0a8a051b42e2b9
Content-Type: text/plain; charset=UTF-8

Oh, very nice - that'd be very useful for storing record types indexed by a
field. And to me it solves the problem motivating this thread - there is
some danger involved, but in practice no more than that involved in
implementing custom comparators.

Do you know why it didn't make it into the standard - was it a question of
safety or utility?
On 19 Jul 2015 17:17, "Magnus Fromreide" <magfr@lysator.liu.se> wrote:

> On Sun, Jul 19, 2015 at 12:10:42AM -0700, Edward Catmur wrote:
> > What's the difference between std::tree and std::set with a non-const
> value_type?
>
> tree allows you to specify how the value_type should be converted to the
> key_type and doesn't force key_type to be equal to value_type.
>
> template <class T, class C, class A>
> using set<T, C, A> = tree<T, T, C, identity, A>;
>
> template <class K, class V, class C, class A>
> using map<K, V, A> = tree<pair<const K, V>, C, select1st, A>;
>
> tree was in stlport back in the days, but it isn't part of std.
>
> /MF
>
> --
>
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/ZYpXVxq5WBs/unsubscribe
> .
> To unsubscribe from this group and all its topics, 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/.
>

--

---
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/.

--047d7bb042722d0a8a051b42e2b9
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<p dir=3D"ltr">Oh, very nice - that&#39;d be very useful for storing record=
 types indexed by a field. And to me it solves the problem motivating this =
thread - there is some danger involved, but in practice no more than that i=
nvolved in implementing custom comparators. </p>
<p dir=3D"ltr">Do you know why it didn&#39;t make it into the standard - wa=
s it a question of safety or utility? </p>
<div class=3D"gmail_quote">On 19 Jul 2015 17:17, &quot;Magnus Fromreide&quo=
t; &lt;<a href=3D"mailto:magfr@lysator.liu.se">magfr@lysator.liu.se</a>&gt;=
 wrote:<br type=3D"attribution"><blockquote class=3D"gmail_quote" style=3D"=
margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On Sun, Jul =
19, 2015 at 12:10:42AM -0700, Edward Catmur wrote:<br>
&gt; What&#39;s the difference between std::tree and std::set with a non-co=
nst value_type?<br>
<br>
tree allows you to specify how the value_type should be converted to the<br=
>
key_type and doesn&#39;t force key_type to be equal to value_type.<br>
<br>
template &lt;class T, class C, class A&gt;<br>
using set&lt;T, C, A&gt; =3D tree&lt;T, T, C, identity, A&gt;;<br>
<br>
template &lt;class K, class V, class C, class A&gt;<br>
using map&lt;K, V, A&gt; =3D tree&lt;pair&lt;const K, V&gt;, C, select1st, =
A&gt;;<br>
<br>
tree was in stlport back in the days, but it isn&#39;t part of std.<br>
<br>
/MF<br>
<br>
--<br>
<br>
---<br>
You received this message because you are subscribed to a topic in the Goog=
le Groups &quot;ISO C++ Standard - Future Proposals&quot; group.<br>
To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/=
a/isocpp.org/d/topic/std-proposals/ZYpXVxq5WBs/unsubscribe" rel=3D"noreferr=
er" target=3D"_blank">https://groups.google.com/a/isocpp.org/d/topic/std-pr=
oposals/ZYpXVxq5WBs/unsubscribe</a>.<br>
To unsubscribe from this group and all its topics, send an email to <a href=
=3D"mailto:std-proposals%2Bunsubscribe@isocpp.org">std-proposals+unsubscrib=
e@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/" rel=3D"noreferrer" target=3D"_blank">http://groups.google.c=
om/a/isocpp.org/group/std-proposals/</a>.<br>
</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&quot; 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 />

--047d7bb042722d0a8a051b42e2b9--

.