Topic: enum traits


Author: fmatthew5876@gmail.com
Date: Fri, 10 Jan 2014 22:47:48 -0800 (PST)
Raw View
------=_Part_799_33431153.1389422868783
Content-Type: text/plain; charset=ISO-8859-1

Enums are one of my favorite tools for efficently labeling collections, but
we need to be able to query more information about them.

I'd like to suggest some form of enum traits.

template <typename E>
struct enum_traits<E> {
  static_assert(is_enum<E>::value, "Only valid for enums!");

  typedef /* underlying type */ value_type;
  static constexpr const value_type min = /* minimum value of enum */
  static constexpr const value_type max = /* maximum value of enum */
  static constexpr const value_type ubound = /* maximum value of enum+1.
Not present (does not compile if queried) if max ==
numeric_limits<value_type>::max(). (Note: this is the most useful value)*/

  static constexpr const size_t count = /* Number of enum tags */
  static constexpr const size_t distinct = /* Number of enum tags with
distinct values */
  static constexpr const bool is_contiguious = /* true if enum values are
contiguous */
  static constexpr const bool is_regular = is_contiguous && min ==
value_type(0);
  static constexpr const bool has_zero = /* true if zero is an enum value */
  static constexpr const bool has_postive = /* true if at least one enum
value is positive */
  static constexpr const bool all_postive = /* true if all enum values are
positive */
  static constexpr const bool has_negative = /* true if at least one enum
value is negative */
  static constexpr const bool all_negative = /* true if all enum values are
negative */

//Utilities to enable foreach, compiler generated
  class iterator : public std::bidirectional_iterator<E> {
    public:
      E operator*();
      //iterator stuff, operator++ goes to next enum value in operator<()
order.
  };
  class reverse_iterator;
  struct range {

    iterator begin();
    iterator end();

    reverse_iterator rbegin();
    reverse_iterator rend();
  };

  range<E> loop();
};

//foreach loop over enum values
for(auto e : enum_traits<E>::loop()) {
};

//Create tables keyed by enums, standard library component
template <typename E, typename T, typename CMP = std::equal_to>
class enum_table {
  //static asserts if li.size() != enum_traits<E>::distinct;
  constexpr enum_table(std::initializer_list<T> li);
  constexpr enum_table(const enum_table&) = default;
  constexpr enum_table(enum_table&&) = default;
  constexpr enum_table& operator=(const enum_table&) = default;
  constexpr enum_table& operator=(enum_table&&) = default;

  constexpr const T& operator[E tag] const;
  constexpr bool lookup(const T& value, E& tag) const;
  constexpr bool lookup(T&& value, E& tag) const;
  constexpr size_t size() const;

  class iterator : std::bidirectional_iterator<std::pair<E, const T&>> {};
  class reverse_iterator;

  constexpr iterator begin();
  constexpr iterator end();
  constexpr reverse_iterator rbegin();
  constexpr reverse_iterator rend();

  constexpr iterator find(E tag);
  template <typename Comparable>
  constexpr iterator find(Comparable&& c); //lookup using CMP(const T&,
C&&) or CMP(const T&, const C&) using perfect forwarding
  constexpr iterator find(T&& value); //lookup using CMP()
};

template <typename E>
using enum_strtable = enum_table<E, const char*, [](const char* l, const
char* r){ return strcmp(l, r) == 0; }>;


//Usage
enum Color {
  kRed,
  kGreen,
  kBlue
};

//Could be place in binary .rodata section.
constexpr const enumstr_table<Color> color_tbl = { "Red", "Blue", "Green" };

assert(!strcmp(color_tbl[kRed], "Red"));
assert(color_tbl.find("Red") != color_tbl.end());

I really want this for ubound, and loop(), and runtime string tables but
while we're at it, there's a lot of cool stuff we could add.
Rationale here:
https://groups.google.com/forum/#!searchin/comp.lang.c$2B$2B.moderated/enum/comp.lang.c++.moderated/RpUiU9utY48/N-oUkAo5oIoJ

Other extensions I'd love to see:
* enum bitmasks as a real type, easy and expressive to declare, strict
rules about logical operator comparisons. Only the tags in the enum can use
binary logical operations with one another.
* concepts in the enum declaration to enforce restrictions (is_contiguous,
min == 0, etc..)


--

---
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_799_33431153.1389422868783
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Enums are one of my favorite tools for efficently labeling=
 collections, but we need to be able to query more information about them.<=
div><br></div><div>I'd like to suggest some form of enum traits.&nbsp;</div=
><div><br></div><div>template &lt;typename E&gt;</div><div>struct enum_trai=
ts&lt;E&gt; {</div><div>&nbsp; static_assert(is_enum&lt;E&gt;::value, "Only=
 valid for enums!");</div><div>&nbsp;&nbsp;</div><div>&nbsp; typedef /* und=
erlying type */ value_type;</div><div>&nbsp; static constexpr const value_t=
ype min =3D /* minimum value of enum */</div><div>&nbsp; static constexpr c=
onst value_type max =3D /* maximum value of enum */</div><div>&nbsp; static=
 constexpr const value_type ubound =3D /* maximum value of enum+1. Not pres=
ent (does not compile if queried) if max =3D=3D numeric_limits&lt;value_typ=
e&gt;::max(). (Note: this is the most useful value)*/</div><div><br></div><=
div>&nbsp; static constexpr const size_t count =3D /* Number of enum tags *=
/</div><div>&nbsp; static constexpr const size_t distinct =3D /* Number of =
enum tags with distinct values */&nbsp;</div><div>&nbsp; static constexpr c=
onst bool is_contiguious =3D /* true if enum values are contiguous */</div>=
<div>&nbsp; static constexpr const bool is_regular =3D is_contiguous &amp;&=
amp; min =3D=3D value_type(0);</div><div>&nbsp; static constexpr const bool=
 has_zero =3D /* true if zero is an enum value */</div><div>&nbsp; static c=
onstexpr const bool has_postive =3D /* true if at least one enum value is p=
ositive */</div><div>&nbsp; static constexpr const bool all_postive =3D /* =
true if all enum values are positive */</div><div>&nbsp; static constexpr c=
onst bool has_negative =3D /* true if at least one enum value is negative *=
/</div><div>&nbsp; static constexpr const bool all_negative =3D /* true if =
all enum values are negative */</div><div><br></div><div>//Utilities to ena=
ble foreach, compiler generated</div><div>&nbsp; class iterator : public st=
d::bidirectional_iterator&lt;E&gt; {</div><div>&nbsp; &nbsp; public:</div><=
div>&nbsp; &nbsp; &nbsp; E operator*();</div><div>&nbsp; &nbsp; &nbsp; //it=
erator stuff, operator++ goes to next enum value in operator&lt;() order.</=
div><div>&nbsp; };</div><div>&nbsp; class reverse_iterator;</div><div>&nbsp=
; struct range {</div><div><br></div><div>&nbsp; &nbsp; iterator begin();</=
div><div>&nbsp; &nbsp; iterator end();</div><div><br></div><div>&nbsp; &nbs=
p; reverse_iterator rbegin();</div><div>&nbsp; &nbsp; reverse_iterator rend=
();<br>&nbsp; };</div><div><br></div><div>&nbsp; range&lt;E&gt; loop();</di=
v><div>};</div><div><br></div><div>//foreach loop over enum values</div><di=
v>for(auto e : enum_traits&lt;E&gt;::loop()) {<br>};</div><div><br></div><d=
iv>//Create tables keyed by enums, standard library component</div><div>tem=
plate &lt;typename E, typename T, typename CMP =3D std::equal_to&gt;</div><=
div>class enum_table {</div><div>&nbsp; //static asserts if li.size() !=3D =
enum_traits&lt;E&gt;::distinct;</div><div>&nbsp; constexpr enum_table(std::=
initializer_list&lt;T&gt; li);</div><div>&nbsp; constexpr enum_table(const =
enum_table&amp;) =3D default;</div><div>&nbsp; constexpr enum_table(enum_ta=
ble&amp;&amp;) =3D default;</div><div><div>&nbsp; constexpr enum_table&amp;=
 operator=3D(const enum_table&amp;) =3D default;</div><div>&nbsp; constexpr=
 enum_table&amp; operator=3D(enum_table&amp;&amp;) =3D default;</div></div>=
<div><br></div><div>&nbsp; constexpr const T&amp; operator[E tag] const;</d=
iv><div>&nbsp; constexpr bool lookup(const T&amp; value, E&amp; tag) const;=
</div><div>&nbsp; constexpr bool lookup(T&amp;&amp; value, E&amp; tag) cons=
t;</div><div>&nbsp; constexpr size_t size() const;</div><div><br></div><div=
>&nbsp; class iterator : std::bidirectional_iterator&lt;std::pair&lt;E, con=
st T&amp;&gt;&gt; {};</div><div>&nbsp; class reverse_iterator;</div><div>&n=
bsp;&nbsp;</div><div>&nbsp; constexpr iterator begin();</div><div>&nbsp; co=
nstexpr iterator end();</div><div><div>&nbsp; constexpr reverse_iterator rb=
egin();</div><div>&nbsp; constexpr reverse_iterator rend();</div><div><br><=
/div><div>&nbsp; constexpr iterator find(E tag);</div><div>&nbsp; template =
&lt;typename Comparable&gt;</div><div>&nbsp; constexpr iterator find(Compar=
able&amp;&amp; c); //lookup using CMP(const T&amp;, C&amp;&amp;) or CMP(con=
st T&amp;, const C&amp;) using perfect forwarding</div><div>&nbsp; constexp=
r iterator find(T&amp;&amp; value); //lookup using CMP()</div>};</div><div>=
<br></div><div>template &lt;typename E&gt;</div><div>using enum_strtable =
=3D enum_table&lt;E, const char*, [](const char* l, const char* r){ return =
strcmp(l, r) =3D=3D 0; }&gt;;</div><div><br></div><div><br></div><div>//Usa=
ge</div><div>enum Color {<br>&nbsp; kRed,</div><div>&nbsp; kGreen,</div><di=
v>&nbsp; kBlue</div><div>};</div><div><br></div><div>//Could be place in bi=
nary .rodata section.</div><div>constexpr const enumstr_table&lt;Color&gt; =
color_tbl =3D { "Red", "Blue", "Green" };</div><div><br></div><div>assert(!=
strcmp(color_tbl[kRed], "Red"));</div><div>assert(color_tbl.find("Red") !=
=3D color_tbl.end());</div><div><br></div><div>I really want this for uboun=
d, and loop(), and runtime string tables but while we're at it, there's a l=
ot of cool stuff we could add.</div><div>Rationale here:</div><div><a href=
=3D"https://groups.google.com/forum/#!searchin/comp.lang.c$2B$2B.moderated/=
enum/comp.lang.c++.moderated/RpUiU9utY48/N-oUkAo5oIoJ">https://groups.googl=
e.com/forum/#!searchin/comp.lang.c$2B$2B.moderated/enum/comp.lang.c++.moder=
ated/RpUiU9utY48/N-oUkAo5oIoJ</a><br></div><div><br></div><div>Other extens=
ions I'd love to see:</div><div>* enum bitmasks as a real type, easy and ex=
pressive to declare, strict rules about logical operator comparisons. Only =
the tags in the enum can use binary logical operations with one another.</d=
iv><div>* concepts in the enum declaration to enforce restrictions (is_cont=
iguous, min =3D=3D 0, etc..)</div><div><br></div><div><br></div></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_799_33431153.1389422868783--

.


Author: fmatthew5876@gmail.com
Date: Fri, 10 Jan 2014 22:50:46 -0800 (PST)
Raw View
------=_Part_1484_3836453.1389423046626
Content-Type: text/plain; charset=ISO-8859-1

Or even better, use std::string_view for the enum_strtable.

On Saturday, January 11, 2014 1:47:48 AM UTC-5, fmatth...@gmail.com wrote:
>
> Enums are one of my favorite tools for efficently labeling collections,
> but we need to be able to query more information about them.
>
> I'd like to suggest some form of enum traits.
>
> template <typename E>
> struct enum_traits<E> {
>   static_assert(is_enum<E>::value, "Only valid for enums!");
>
>   typedef /* underlying type */ value_type;
>   static constexpr const value_type min = /* minimum value of enum */
>   static constexpr const value_type max = /* maximum value of enum */
>   static constexpr const value_type ubound = /* maximum value of enum+1.
> Not present (does not compile if queried) if max ==
> numeric_limits<value_type>::max(). (Note: this is the most useful value)*/
>
>   static constexpr const size_t count = /* Number of enum tags */
>   static constexpr const size_t distinct = /* Number of enum tags with
> distinct values */
>   static constexpr const bool is_contiguious = /* true if enum values are
> contiguous */
>   static constexpr const bool is_regular = is_contiguous && min ==
> value_type(0);
>   static constexpr const bool has_zero = /* true if zero is an enum value
> */
>   static constexpr const bool has_postive = /* true if at least one enum
> value is positive */
>   static constexpr const bool all_postive = /* true if all enum values are
> positive */
>   static constexpr const bool has_negative = /* true if at least one enum
> value is negative */
>   static constexpr const bool all_negative = /* true if all enum values
> are negative */
>
> //Utilities to enable foreach, compiler generated
>   class iterator : public std::bidirectional_iterator<E> {
>     public:
>       E operator*();
>       //iterator stuff, operator++ goes to next enum value in operator<()
> order.
>   };
>   class reverse_iterator;
>   struct range {
>
>     iterator begin();
>     iterator end();
>
>     reverse_iterator rbegin();
>     reverse_iterator rend();
>   };
>
>   range<E> loop();
> };
>
> //foreach loop over enum values
> for(auto e : enum_traits<E>::loop()) {
> };
>
> //Create tables keyed by enums, standard library component
> template <typename E, typename T, typename CMP = std::equal_to>
> class enum_table {
>   //static asserts if li.size() != enum_traits<E>::distinct;
>   constexpr enum_table(std::initializer_list<T> li);
>   constexpr enum_table(const enum_table&) = default;
>   constexpr enum_table(enum_table&&) = default;
>   constexpr enum_table& operator=(const enum_table&) = default;
>   constexpr enum_table& operator=(enum_table&&) = default;
>
>   constexpr const T& operator[E tag] const;
>   constexpr bool lookup(const T& value, E& tag) const;
>   constexpr bool lookup(T&& value, E& tag) const;
>   constexpr size_t size() const;
>
>   class iterator : std::bidirectional_iterator<std::pair<E, const T&>> {};
>   class reverse_iterator;
>
>   constexpr iterator begin();
>   constexpr iterator end();
>   constexpr reverse_iterator rbegin();
>   constexpr reverse_iterator rend();
>
>   constexpr iterator find(E tag);
>   template <typename Comparable>
>   constexpr iterator find(Comparable&& c); //lookup using CMP(const T&,
> C&&) or CMP(const T&, const C&) using perfect forwarding
>   constexpr iterator find(T&& value); //lookup using CMP()
> };
>
> template <typename E>
> using enum_strtable = enum_table<E, const char*, [](const char* l, const
> char* r){ return strcmp(l, r) == 0; }>;
>
>
> //Usage
> enum Color {
>   kRed,
>   kGreen,
>   kBlue
> };
>
> //Could be place in binary .rodata section.
> constexpr const enumstr_table<Color> color_tbl = { "Red", "Blue", "Green"
> };
>
> assert(!strcmp(color_tbl[kRed], "Red"));
> assert(color_tbl.find("Red") != color_tbl.end());
>
> I really want this for ubound, and loop(), and runtime string tables but
> while we're at it, there's a lot of cool stuff we could add.
> Rationale here:
>
> https://groups.google.com/forum/#!searchin/comp.lang.c$2B$2B.moderated/enum/comp.lang.c++.moderated/RpUiU9utY48/N-oUkAo5oIoJ
>
> Other extensions I'd love to see:
> * enum bitmasks as a real type, easy and expressive to declare, strict
> rules about logical operator comparisons. Only the tags in the enum can use
> binary logical operations with one another.
> * concepts in the enum declaration to enforce restrictions (is_contiguous,
> min == 0, etc..)
>
>
>

--

---
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_1484_3836453.1389423046626
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Or even better, use std::string_view for the enum_strtable=
..<br><br>On Saturday, January 11, 2014 1:47:48 AM UTC-5, fmatth...@gmail.co=
m 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">Enums=
 are one of my favorite tools for efficently labeling collections, but we n=
eed to be able to query more information about them.<div><br></div><div>I'd=
 like to suggest some form of enum traits.&nbsp;</div><div><br></div><div>t=
emplate &lt;typename E&gt;</div><div>struct enum_traits&lt;E&gt; {</div><di=
v>&nbsp; static_assert(is_enum&lt;E&gt;::<wbr>value, "Only valid for enums!=
");</div><div>&nbsp;&nbsp;</div><div>&nbsp; typedef /* underlying type */ v=
alue_type;</div><div>&nbsp; static constexpr const value_type min =3D /* mi=
nimum value of enum */</div><div>&nbsp; static constexpr const value_type m=
ax =3D /* maximum value of enum */</div><div>&nbsp; static constexpr const =
value_type ubound =3D /* maximum value of enum+1. Not present (does not com=
pile if queried) if max =3D=3D numeric_limits&lt;value_type&gt;::<wbr>max()=
.. (Note: this is the most useful value)*/</div><div><br></div><div>&nbsp; s=
tatic constexpr const size_t count =3D /* Number of enum tags */</div><div>=
&nbsp; static constexpr const size_t distinct =3D /* Number of enum tags wi=
th distinct values */&nbsp;</div><div>&nbsp; static constexpr const bool is=
_contiguious =3D /* true if enum values are contiguous */</div><div>&nbsp; =
static constexpr const bool is_regular =3D is_contiguous &amp;&amp; min =3D=
=3D value_type(0);</div><div>&nbsp; static constexpr const bool has_zero =
=3D /* true if zero is an enum value */</div><div>&nbsp; static constexpr c=
onst bool has_postive =3D /* true if at least one enum value is positive */=
</div><div>&nbsp; static constexpr const bool all_postive =3D /* true if al=
l enum values are positive */</div><div>&nbsp; static constexpr const bool =
has_negative =3D /* true if at least one enum value is negative */</div><di=
v>&nbsp; static constexpr const bool all_negative =3D /* true if all enum v=
alues are negative */</div><div><br></div><div>//Utilities to enable foreac=
h, compiler generated</div><div>&nbsp; class iterator : public std::bidirec=
tional_iterator&lt;E&gt; {</div><div>&nbsp; &nbsp; public:</div><div>&nbsp;=
 &nbsp; &nbsp; E operator*();</div><div>&nbsp; &nbsp; &nbsp; //iterator stu=
ff, operator++ goes to next enum value in operator&lt;() order.</div><div>&=
nbsp; };</div><div>&nbsp; class reverse_iterator;</div><div>&nbsp; struct r=
ange {</div><div><br></div><div>&nbsp; &nbsp; iterator begin();</div><div>&=
nbsp; &nbsp; iterator end();</div><div><br></div><div>&nbsp; &nbsp; reverse=
_iterator rbegin();</div><div>&nbsp; &nbsp; reverse_iterator rend();<br>&nb=
sp; };</div><div><br></div><div>&nbsp; range&lt;E&gt; loop();</div><div>};<=
/div><div><br></div><div>//foreach loop over enum values</div><div>for(auto=
 e : enum_traits&lt;E&gt;::loop()) {<br>};</div><div><br></div><div>//Creat=
e tables keyed by enums, standard library component</div><div>template &lt;=
typename E, typename T, typename CMP =3D std::equal_to&gt;</div><div>class =
enum_table {</div><div>&nbsp; //static asserts if li.size() !=3D enum_trait=
s&lt;E&gt;::distinct;</div><div>&nbsp; constexpr enum_table(std::initialize=
r_<wbr>list&lt;T&gt; li);</div><div>&nbsp; constexpr enum_table(const enum_=
table&amp;) =3D default;</div><div>&nbsp; constexpr enum_table(enum_table&a=
mp;&amp;) =3D default;</div><div><div>&nbsp; constexpr enum_table&amp; oper=
ator=3D(const enum_table&amp;) =3D default;</div><div>&nbsp; constexpr enum=
_table&amp; operator=3D(enum_table&amp;&amp;) =3D default;</div></div><div>=
<br></div><div>&nbsp; constexpr const T&amp; operator[E tag] const;</div><d=
iv>&nbsp; constexpr bool lookup(const T&amp; value, E&amp; tag) const;</div=
><div>&nbsp; constexpr bool lookup(T&amp;&amp; value, E&amp; tag) const;</d=
iv><div>&nbsp; constexpr size_t size() const;</div><div><br></div><div>&nbs=
p; class iterator : std::bidirectional_iterator&lt;<wbr>std::pair&lt;E, con=
st T&amp;&gt;&gt; {};</div><div>&nbsp; class reverse_iterator;</div><div>&n=
bsp;&nbsp;</div><div>&nbsp; constexpr iterator begin();</div><div>&nbsp; co=
nstexpr iterator end();</div><div><div>&nbsp; constexpr reverse_iterator rb=
egin();</div><div>&nbsp; constexpr reverse_iterator rend();</div><div><br><=
/div><div>&nbsp; constexpr iterator find(E tag);</div><div>&nbsp; template =
&lt;typename Comparable&gt;</div><div>&nbsp; constexpr iterator find(Compar=
able&amp;&amp; c); //lookup using CMP(const T&amp;, C&amp;&amp;) or CMP(con=
st T&amp;, const C&amp;) using perfect forwarding</div><div>&nbsp; constexp=
r iterator find(T&amp;&amp; value); //lookup using CMP()</div>};</div><div>=
<br></div><div>template &lt;typename E&gt;</div><div>using enum_strtable =
=3D enum_table&lt;E, const char*, [](const char* l, const char* r){ return =
strcmp(l, r) =3D=3D 0; }&gt;;</div><div><br></div><div><br></div><div>//Usa=
ge</div><div>enum Color {<br>&nbsp; kRed,</div><div>&nbsp; kGreen,</div><di=
v>&nbsp; kBlue</div><div>};</div><div><br></div><div>//Could be place in bi=
nary .rodata section.</div><div>constexpr const enumstr_table&lt;Color&gt; =
color_tbl =3D { "Red", "Blue", "Green" };</div><div><br></div><div>assert(!=
strcmp(color_tbl[kRed]<wbr>, "Red"));</div><div>assert(color_tbl.find("Red"=
) !=3D color_tbl.end());</div><div><br></div><div>I really want this for ub=
ound, and loop(), and runtime string tables but while we're at it, there's =
a lot of cool stuff we could add.</div><div>Rationale here:</div><div><a hr=
ef=3D"https://groups.google.com/forum/#!searchin/comp.lang.c$2B$2B.moderate=
d/enum/comp.lang.c++.moderated/RpUiU9utY48/N-oUkAo5oIoJ" target=3D"_blank" =
onmousedown=3D"this.href=3D'https://groups.google.com/forum/#!searchin/comp=
..lang.c$2B$2B.moderated/enum/comp.lang.c++.moderated/RpUiU9utY48/N-oUkAo5oI=
oJ';return true;" onclick=3D"this.href=3D'https://groups.google.com/forum/#=
!searchin/comp.lang.c$2B$2B.moderated/enum/comp.lang.c++.moderated/RpUiU9ut=
Y48/N-oUkAo5oIoJ';return true;">https://groups.google.com/<wbr>forum/#!sear=
chin/comp.lang.c$<wbr>2B$2B.moderated/enum/comp.<wbr>lang.c++.moderated/<wb=
r>RpUiU9utY48/N-oUkAo5oIoJ</a><br></div><div><br></div><div>Other extension=
s I'd love to see:</div><div>* enum bitmasks as a real type, easy and expre=
ssive to declare, strict rules about logical operator comparisons. Only the=
 tags in the enum can use binary logical operations with one another.</div>=
<div>* concepts in the enum declaration to enforce restrictions (is_contigu=
ous, min =3D=3D 0, etc..)</div><div><br></div><div><br></div></div></blockq=
uote></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_1484_3836453.1389423046626--

.


Author: David Krauss <potswa@gmail.com>
Date: Sat, 11 Jan 2014 15:34:05 +0800
Raw View
On 1/11/14 2:50 PM, fmatthew5876@gmail.com wrote:
> Or even better, use std::string_view for the enum_strtable.

See recent threads, "Enumerator traits, rev. 2", and "enumeration pack
and __enumerator__ template variable".

An existing Clang prototype including generated strings was mentioned in
the latter thread.

--

---
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: Remotion <remotion4d@googlemail.com>
Date: Sat, 11 Jan 2014 06:01:11 -0800 (PST)
Raw View
------=_Part_1720_12637001.1389448871496
Content-Type: text/plain; charset=ISO-8859-1

Yes we need enum_traits but not only them.
Here you can find experimental implementation of traits and clang based
compiler.
https://bitbucket.org/remotion/c-reflection

Here is also proposal for this.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3815.html



On Saturday, January 11, 2014 7:47:48 AM UTC+1, fmatth...@gmail.com wrote:
>
> Enums are one of my favorite tools for efficently labeling collections,
> but we need to be able to query more information about them.
>
> I'd like to suggest some form of enum traits.
>
> template <typename E>
> struct enum_traits<E> {
>   static_assert(is_enum<E>::value, "Only valid for enums!");
>
>   typedef /* underlying type */ value_type;
>   static constexpr const value_type min = /* minimum value of enum */
>   static constexpr const value_type max = /* maximum value of enum */
>   static constexpr const value_type ubound = /* maximum value of enum+1.
> Not present (does not compile if queried) if max ==
> numeric_limits<value_type>::max(). (Note: this is the most useful value)*/
>
>   static constexpr const size_t count = /* Number of enum tags */
>   static constexpr const size_t distinct = /* Number of enum tags with
> distinct values */
>   static constexpr const bool is_contiguious = /* true if enum values are
> contiguous */
>   static constexpr const bool is_regular = is_contiguous && min ==
> value_type(0);
>   static constexpr const bool has_zero = /* true if zero is an enum value
> */
>   static constexpr const bool has_postive = /* true if at least one enum
> value is positive */
>   static constexpr const bool all_postive = /* true if all enum values are
> positive */
>   static constexpr const bool has_negative = /* true if at least one enum
> value is negative */
>   static constexpr const bool all_negative = /* true if all enum values
> are negative */
>
> //Utilities to enable foreach, compiler generated
>   class iterator : public std::bidirectional_iterator<E> {
>     public:
>       E operator*();
>       //iterator stuff, operator++ goes to next enum value in operator<()
> order.
>   };
>   class reverse_iterator;
>   struct range {
>
>     iterator begin();
>     iterator end();
>
>     reverse_iterator rbegin();
>     reverse_iterator rend();
>   };
>
>   range<E> loop();
> };
>
> //foreach loop over enum values
> for(auto e : enum_traits<E>::loop()) {
> };
>
> //Create tables keyed by enums, standard library component
> template <typename E, typename T, typename CMP = std::equal_to>
> class enum_table {
>   //static asserts if li.size() != enum_traits<E>::distinct;
>   constexpr enum_table(std::initializer_list<T> li);
>   constexpr enum_table(const enum_table&) = default;
>   constexpr enum_table(enum_table&&) = default;
>   constexpr enum_table& operator=(const enum_table&) = default;
>   constexpr enum_table& operator=(enum_table&&) = default;
>
>   constexpr const T& operator[E tag] const;
>   constexpr bool lookup(const T& value, E& tag) const;
>   constexpr bool lookup(T&& value, E& tag) const;
>   constexpr size_t size() const;
>
>   class iterator : std::bidirectional_iterator<std::pair<E, const T&>> {};
>   class reverse_iterator;
>
>   constexpr iterator begin();
>   constexpr iterator end();
>   constexpr reverse_iterator rbegin();
>   constexpr reverse_iterator rend();
>
>   constexpr iterator find(E tag);
>   template <typename Comparable>
>   constexpr iterator find(Comparable&& c); //lookup using CMP(const T&,
> C&&) or CMP(const T&, const C&) using perfect forwarding
>   constexpr iterator find(T&& value); //lookup using CMP()
> };
>
> template <typename E>
> using enum_strtable = enum_table<E, const char*, [](const char* l, const
> char* r){ return strcmp(l, r) == 0; }>;
>
>
> //Usage
> enum Color {
>   kRed,
>   kGreen,
>   kBlue
> };
>
> //Could be place in binary .rodata section.
> constexpr const enumstr_table<Color> color_tbl = { "Red", "Blue", "Green"
> };
>
> assert(!strcmp(color_tbl[kRed], "Red"));
> assert(color_tbl.find("Red") != color_tbl.end());
>
> I really want this for ubound, and loop(), and runtime string tables but
> while we're at it, there's a lot of cool stuff we could add.
> Rationale here:
>
> https://groups.google.com/forum/#!searchin/comp.lang.c$2B$2B.moderated/enum/comp.lang.c++.moderated/RpUiU9utY48/N-oUkAo5oIoJ
>
> Other extensions I'd love to see:
> * enum bitmasks as a real type, easy and expressive to declare, strict
> rules about logical operator comparisons. Only the tags in the enum can use
> binary logical operations with one another.
> * concepts in the enum declaration to enforce restrictions (is_contiguous,
> min == 0, etc..)
>
>
>

--

---
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_1720_12637001.1389448871496
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Yes we need enum_traits but not only them.<br>Here you can=
 find experimental implementation of traits and clang based compiler.<br>ht=
tps://bitbucket.org/remotion/c-reflection<br><br>Here is also proposal for =
this.<br><a href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013=
/n3815.html" target=3D"_blank">http://www.open-std.org/jtc1/<wbr>sc22/wg21/=
docs/papers/2013/<wbr>n3815.html</a><br><br><br><br>On Saturday, January 11=
, 2014 7:47:48 AM UTC+1, fmatth...@gmail.com 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">Enums are one of my favorite tools fo=
r efficently labeling collections, but we need to be able to query more inf=
ormation about them.<div><br></div><div>I'd like to suggest some form of en=
um traits.&nbsp;</div><div><br></div><div>template &lt;typename E&gt;</div>=
<div>struct enum_traits&lt;E&gt; {</div><div>&nbsp; static_assert(is_enum&l=
t;E&gt;::<wbr>value, "Only valid for enums!");</div><div>&nbsp;&nbsp;</div>=
<div>&nbsp; typedef /* underlying type */ value_type;</div><div>&nbsp; stat=
ic constexpr const value_type min =3D /* minimum value of enum */</div><div=
>&nbsp; static constexpr const value_type max =3D /* maximum value of enum =
*/</div><div>&nbsp; static constexpr const value_type ubound =3D /* maximum=
 value of enum+1. Not present (does not compile if queried) if max =3D=3D n=
umeric_limits&lt;value_type&gt;::<wbr>max(). (Note: this is the most useful=
 value)*/</div><div><br></div><div>&nbsp; static constexpr const size_t cou=
nt =3D /* Number of enum tags */</div><div>&nbsp; static constexpr const si=
ze_t distinct =3D /* Number of enum tags with distinct values */&nbsp;</div=
><div>&nbsp; static constexpr const bool is_contiguious =3D /* true if enum=
 values are contiguous */</div><div>&nbsp; static constexpr const bool is_r=
egular =3D is_contiguous &amp;&amp; min =3D=3D value_type(0);</div><div>&nb=
sp; static constexpr const bool has_zero =3D /* true if zero is an enum val=
ue */</div><div>&nbsp; static constexpr const bool has_postive =3D /* true =
if at least one enum value is positive */</div><div>&nbsp; static constexpr=
 const bool all_postive =3D /* true if all enum values are positive */</div=
><div>&nbsp; static constexpr const bool has_negative =3D /* true if at lea=
st one enum value is negative */</div><div>&nbsp; static constexpr const bo=
ol all_negative =3D /* true if all enum values are negative */</div><div><b=
r></div><div>//Utilities to enable foreach, compiler generated</div><div>&n=
bsp; class iterator : public std::bidirectional_iterator&lt;E&gt; {</div><d=
iv>&nbsp; &nbsp; public:</div><div>&nbsp; &nbsp; &nbsp; E operator*();</div=
><div>&nbsp; &nbsp; &nbsp; //iterator stuff, operator++ goes to next enum v=
alue in operator&lt;() order.</div><div>&nbsp; };</div><div>&nbsp; class re=
verse_iterator;</div><div>&nbsp; struct range {</div><div><br></div><div>&n=
bsp; &nbsp; iterator begin();</div><div>&nbsp; &nbsp; iterator end();</div>=
<div><br></div><div>&nbsp; &nbsp; reverse_iterator rbegin();</div><div>&nbs=
p; &nbsp; reverse_iterator rend();<br>&nbsp; };</div><div><br></div><div>&n=
bsp; range&lt;E&gt; loop();</div><div>};</div><div><br></div><div>//foreach=
 loop over enum values</div><div>for(auto e : enum_traits&lt;E&gt;::loop())=
 {<br>};</div><div><br></div><div>//Create tables keyed by enums, standard =
library component</div><div>template &lt;typename E, typename T, typename C=
MP =3D std::equal_to&gt;</div><div>class enum_table {</div><div>&nbsp; //st=
atic asserts if li.size() !=3D enum_traits&lt;E&gt;::distinct;</div><div>&n=
bsp; constexpr enum_table(std::initializer_<wbr>list&lt;T&gt; li);</div><di=
v>&nbsp; constexpr enum_table(const enum_table&amp;) =3D default;</div><div=
>&nbsp; constexpr enum_table(enum_table&amp;&amp;) =3D default;</div><div><=
div>&nbsp; constexpr enum_table&amp; operator=3D(const enum_table&amp;) =3D=
 default;</div><div>&nbsp; constexpr enum_table&amp; operator=3D(enum_table=
&amp;&amp;) =3D default;</div></div><div><br></div><div>&nbsp; constexpr co=
nst T&amp; operator[E tag] const;</div><div>&nbsp; constexpr bool lookup(co=
nst T&amp; value, E&amp; tag) const;</div><div>&nbsp; constexpr bool lookup=
(T&amp;&amp; value, E&amp; tag) const;</div><div>&nbsp; constexpr size_t si=
ze() const;</div><div><br></div><div>&nbsp; class iterator : std::bidirecti=
onal_iterator&lt;<wbr>std::pair&lt;E, const T&amp;&gt;&gt; {};</div><div>&n=
bsp; class reverse_iterator;</div><div>&nbsp;&nbsp;</div><div>&nbsp; conste=
xpr iterator begin();</div><div>&nbsp; constexpr iterator end();</div><div>=
<div>&nbsp; constexpr reverse_iterator rbegin();</div><div>&nbsp; constexpr=
 reverse_iterator rend();</div><div><br></div><div>&nbsp; constexpr iterato=
r find(E tag);</div><div>&nbsp; template &lt;typename Comparable&gt;</div><=
div>&nbsp; constexpr iterator find(Comparable&amp;&amp; c); //lookup using =
CMP(const T&amp;, C&amp;&amp;) or CMP(const T&amp;, const C&amp;) using per=
fect forwarding</div><div>&nbsp; constexpr iterator find(T&amp;&amp; value)=
; //lookup using CMP()</div>};</div><div><br></div><div>template &lt;typena=
me E&gt;</div><div>using enum_strtable =3D enum_table&lt;E, const char*, []=
(const char* l, const char* r){ return strcmp(l, r) =3D=3D 0; }&gt;;</div><=
div><br></div><div><br></div><div>//Usage</div><div>enum Color {<br>&nbsp; =
kRed,</div><div>&nbsp; kGreen,</div><div>&nbsp; kBlue</div><div>};</div><di=
v><br></div><div>//Could be place in binary .rodata section.</div><div>cons=
texpr const enumstr_table&lt;Color&gt; color_tbl =3D { "Red", "Blue", "Gree=
n" };</div><div><br></div><div>assert(!strcmp(color_tbl[kRed]<wbr>, "Red"))=
;</div><div>assert(color_tbl.find("Red") !=3D color_tbl.end());</div><div><=
br></div><div>I really want this for ubound, and loop(), and runtime string=
 tables but while we're at it, there's a lot of cool stuff we could add.</d=
iv><div>Rationale here:</div><div><a href=3D"https://groups.google.com/foru=
m/#!searchin/comp.lang.c$2B$2B.moderated/enum/comp.lang.c++.moderated/RpUiU=
9utY48/N-oUkAo5oIoJ" target=3D"_blank" onmousedown=3D"this.href=3D'https://=
groups.google.com/forum/#!searchin/comp.lang.c$2B$2B.moderated/enum/comp.la=
ng.c++.moderated/RpUiU9utY48/N-oUkAo5oIoJ';return true;" onclick=3D"this.hr=
ef=3D'https://groups.google.com/forum/#!searchin/comp.lang.c$2B$2B.moderate=
d/enum/comp.lang.c++.moderated/RpUiU9utY48/N-oUkAo5oIoJ';return true;">http=
s://groups.google.com/<wbr>forum/#!searchin/comp.lang.c$<wbr>2B$2B.moderate=
d/enum/comp.<wbr>lang.c++.moderated/<wbr>RpUiU9utY48/N-oUkAo5oIoJ</a><br></=
div><div><br></div><div>Other extensions I'd love to see:</div><div>* enum =
bitmasks as a real type, easy and expressive to declare, strict rules about=
 logical operator comparisons. Only the tags in the enum can use binary log=
ical operations with one another.</div><div>* concepts in the enum declarat=
ion to enforce restrictions (is_contiguous, min =3D=3D 0, etc..)</div><div>=
<br></div><div><br></div></div></blockquote></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_1720_12637001.1389448871496--

.


Author: fmatthew5876@gmail.com
Date: Sat, 11 Jan 2014 06:59:50 -0800 (PST)
Raw View
------=_Part_26_24717104.1389452390106
Content-Type: text/plain; charset=ISO-8859-1

I think having a built in string table where the strings match the enum tag
names exactly is too limiting. I'd like to define my own string mapping and
I do this extremely often in my current projects. Even having multiple
string mappings such as name and description is incredibly useful. One
example is command line arguments but there are many others. Having a
generic table of other types would also be useful.

Perhaps this enum table could be a separate proposal. It's more of a
library component to extend enums. While its use case is not really related
to reflection, its implementation would require reflection.



On Saturday, January 11, 2014 9:01:11 AM UTC-5, Remotion wrote:
>
> Yes we need enum_traits but not only them.
> Here you can find experimental implementation of traits and clang based
> compiler.
> https://bitbucket.org/remotion/c-reflection
>
> Here is also proposal for this.
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3815.html
>
>
>
> On Saturday, January 11, 2014 7:47:48 AM UTC+1, fmatth...@gmail.com wrote:
>>
>> Enums are one of my favorite tools for efficently labeling collections,
>> but we need to be able to query more information about them.
>>
>> I'd like to suggest some form of enum traits.
>>
>> template <typename E>
>> struct enum_traits<E> {
>>   static_assert(is_enum<E>::value, "Only valid for enums!");
>>
>>   typedef /* underlying type */ value_type;
>>   static constexpr const value_type min = /* minimum value of enum */
>>   static constexpr const value_type max = /* maximum value of enum */
>>   static constexpr const value_type ubound = /* maximum value of enum+1.
>> Not present (does not compile if queried) if max ==
>> numeric_limits<value_type>::max(). (Note: this is the most useful value)*/
>>
>>   static constexpr const size_t count = /* Number of enum tags */
>>   static constexpr const size_t distinct = /* Number of enum tags with
>> distinct values */
>>   static constexpr const bool is_contiguious = /* true if enum values are
>> contiguous */
>>   static constexpr const bool is_regular = is_contiguous && min ==
>> value_type(0);
>>   static constexpr const bool has_zero = /* true if zero is an enum value
>> */
>>   static constexpr const bool has_postive = /* true if at least one enum
>> value is positive */
>>   static constexpr const bool all_postive = /* true if all enum values
>> are positive */
>>   static constexpr const bool has_negative = /* true if at least one enum
>> value is negative */
>>   static constexpr const bool all_negative = /* true if all enum values
>> are negative */
>>
>> //Utilities to enable foreach, compiler generated
>>   class iterator : public std::bidirectional_iterator<E> {
>>     public:
>>       E operator*();
>>       //iterator stuff, operator++ goes to next enum value in operator<()
>> order.
>>   };
>>   class reverse_iterator;
>>   struct range {
>>
>>     iterator begin();
>>     iterator end();
>>
>>     reverse_iterator rbegin();
>>     reverse_iterator rend();
>>   };
>>
>>   range<E> loop();
>> };
>>
>> //foreach loop over enum values
>> for(auto e : enum_traits<E>::loop()) {
>> };
>>
>> //Create tables keyed by enums, standard library component
>> template <typename E, typename T, typename CMP = std::equal_to>
>> class enum_table {
>>   //static asserts if li.size() != enum_traits<E>::distinct;
>>   constexpr enum_table(std::initializer_list<T> li);
>>   constexpr enum_table(const enum_table&) = default;
>>   constexpr enum_table(enum_table&&) = default;
>>   constexpr enum_table& operator=(const enum_table&) = default;
>>   constexpr enum_table& operator=(enum_table&&) = default;
>>
>>   constexpr const T& operator[E tag] const;
>>   constexpr bool lookup(const T& value, E& tag) const;
>>   constexpr bool lookup(T&& value, E& tag) const;
>>   constexpr size_t size() const;
>>
>>   class iterator : std::bidirectional_iterator<std::pair<E, const T&>> {};
>>   class reverse_iterator;
>>
>>   constexpr iterator begin();
>>   constexpr iterator end();
>>   constexpr reverse_iterator rbegin();
>>   constexpr reverse_iterator rend();
>>
>>   constexpr iterator find(E tag);
>>   template <typename Comparable>
>>   constexpr iterator find(Comparable&& c); //lookup using CMP(const T&,
>> C&&) or CMP(const T&, const C&) using perfect forwarding
>>   constexpr iterator find(T&& value); //lookup using CMP()
>> };
>>
>> template <typename E>
>> using enum_strtable = enum_table<E, const char*, [](const char* l, const
>> char* r){ return strcmp(l, r) == 0; }>;
>>
>>
>> //Usage
>> enum Color {
>>   kRed,
>>   kGreen,
>>   kBlue
>> };
>>
>> //Could be place in binary .rodata section.
>> constexpr const enumstr_table<Color> color_tbl = { "Red", "Blue", "Green"
>> };
>>
>> assert(!strcmp(color_tbl[kRed], "Red"));
>> assert(color_tbl.find("Red") != color_tbl.end());
>>
>> I really want this for ubound, and loop(), and runtime string tables but
>> while we're at it, there's a lot of cool stuff we could add.
>> Rationale here:
>>
>> https://groups.google.com/forum/#!searchin/comp.lang.c$2B$2B.moderated/enum/comp.lang.c++.moderated/RpUiU9utY48/N-oUkAo5oIoJ
>>
>> Other extensions I'd love to see:
>> * enum bitmasks as a real type, easy and expressive to declare, strict
>> rules about logical operator comparisons. Only the tags in the enum can use
>> binary logical operations with one another.
>> * concepts in the enum declaration to enforce restrictions
>> (is_contiguous, min == 0, etc..)
>>
>>
>>

--

---
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_26_24717104.1389452390106
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">I think having a built in string table where the strings m=
atch the enum tag names exactly is too limiting. I'd like to define my own =
string mapping and I do this extremely often in my current projects. Even h=
aving multiple string mappings such as name and description is incredibly u=
seful. One example is command line arguments but there are many others. Hav=
ing a generic table of other types would also be useful.<div><br></div><div=
>Perhaps this enum table could be a separate proposal. It's more of a libra=
ry component to extend enums. While its use case is not really related to r=
eflection, its implementation would require reflection.<br><div><br></div><=
div><br><br>On Saturday, January 11, 2014 9:01:11 AM UTC-5, Remotion wrote:=
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">Yes we need e=
num_traits but not only them.<br>Here you can find experimental implementat=
ion of traits and clang based compiler.<br><a href=3D"https://bitbucket.org=
/remotion/c-reflection" target=3D"_blank" onmousedown=3D"this.href=3D'https=
://www.google.com/url?q\75https%3A%2F%2Fbitbucket.org%2Fremotion%2Fc-reflec=
tion\46sa\75D\46sntz\0751\46usg\75AFQjCNGd00k4f3RkVzm4zaycMKeQAYfl_g';retur=
n true;" onclick=3D"this.href=3D'https://www.google.com/url?q\75https%3A%2F=
%2Fbitbucket.org%2Fremotion%2Fc-reflection\46sa\75D\46sntz\0751\46usg\75AFQ=
jCNGd00k4f3RkVzm4zaycMKeQAYfl_g';return true;">https://bitbucket.org/<wbr>r=
emotion/c-reflection</a><br><br>Here is also proposal for this.<br><a href=
=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3815.html" tar=
get=3D"_blank" onmousedown=3D"this.href=3D'http://www.google.com/url?q\75ht=
tp%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2013%2Fn=
3815.html\46sa\75D\46sntz\0751\46usg\75AFQjCNHwe7liqoidkU5rvKFSWklGuTd4gw';=
return true;" onclick=3D"this.href=3D'http://www.google.com/url?q\75http%3A=
%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2013%2Fn3815.=
html\46sa\75D\46sntz\0751\46usg\75AFQjCNHwe7liqoidkU5rvKFSWklGuTd4gw';retur=
n true;">http://www.open-std.org/jtc1/<wbr>sc22/wg21/docs/papers/2013/<wbr>=
n3815.html</a><br><br><br><br>On Saturday, January 11, 2014 7:47:48 AM UTC+=
1, <a>fmatth...@gmail.com</a> 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">Enums are one of my favorite tools for efficently labelin=
g collections, but we need to be able to query more information about them.=
<div><br></div><div>I'd like to suggest some form of enum traits.&nbsp;</di=
v><div><br></div><div>template &lt;typename E&gt;</div><div>struct enum_tra=
its&lt;E&gt; {</div><div>&nbsp; static_assert(is_enum&lt;E&gt;::<wbr>value,=
 "Only valid for enums!");</div><div>&nbsp;&nbsp;</div><div>&nbsp; typedef =
/* underlying type */ value_type;</div><div>&nbsp; static constexpr const v=
alue_type min =3D /* minimum value of enum */</div><div>&nbsp; static const=
expr const value_type max =3D /* maximum value of enum */</div><div>&nbsp; =
static constexpr const value_type ubound =3D /* maximum value of enum+1. No=
t present (does not compile if queried) if max =3D=3D numeric_limits&lt;val=
ue_type&gt;::<wbr>max(). (Note: this is the most useful value)*/</div><div>=
<br></div><div>&nbsp; static constexpr const size_t count =3D /* Number of =
enum tags */</div><div>&nbsp; static constexpr const size_t distinct =3D /*=
 Number of enum tags with distinct values */&nbsp;</div><div>&nbsp; static =
constexpr const bool is_contiguious =3D /* true if enum values are contiguo=
us */</div><div>&nbsp; static constexpr const bool is_regular =3D is_contig=
uous &amp;&amp; min =3D=3D value_type(0);</div><div>&nbsp; static constexpr=
 const bool has_zero =3D /* true if zero is an enum value */</div><div>&nbs=
p; static constexpr const bool has_postive =3D /* true if at least one enum=
 value is positive */</div><div>&nbsp; static constexpr const bool all_post=
ive =3D /* true if all enum values are positive */</div><div>&nbsp; static =
constexpr const bool has_negative =3D /* true if at least one enum value is=
 negative */</div><div>&nbsp; static constexpr const bool all_negative =3D =
/* true if all enum values are negative */</div><div><br></div><div>//Utili=
ties to enable foreach, compiler generated</div><div>&nbsp; class iterator =
: public std::bidirectional_iterator&lt;E&gt; {</div><div>&nbsp; &nbsp; pub=
lic:</div><div>&nbsp; &nbsp; &nbsp; E operator*();</div><div>&nbsp; &nbsp; =
&nbsp; //iterator stuff, operator++ goes to next enum value in operator&lt;=
() order.</div><div>&nbsp; };</div><div>&nbsp; class reverse_iterator;</div=
><div>&nbsp; struct range {</div><div><br></div><div>&nbsp; &nbsp; iterator=
 begin();</div><div>&nbsp; &nbsp; iterator end();</div><div><br></div><div>=
&nbsp; &nbsp; reverse_iterator rbegin();</div><div>&nbsp; &nbsp; reverse_it=
erator rend();<br>&nbsp; };</div><div><br></div><div>&nbsp; range&lt;E&gt; =
loop();</div><div>};</div><div><br></div><div>//foreach loop over enum valu=
es</div><div>for(auto e : enum_traits&lt;E&gt;::loop()) {<br>};</div><div><=
br></div><div>//Create tables keyed by enums, standard library component</d=
iv><div>template &lt;typename E, typename T, typename CMP =3D std::equal_to=
&gt;</div><div>class enum_table {</div><div>&nbsp; //static asserts if li.s=
ize() !=3D enum_traits&lt;E&gt;::distinct;</div><div>&nbsp; constexpr enum_=
table(std::initializer_<wbr>list&lt;T&gt; li);</div><div>&nbsp; constexpr e=
num_table(const enum_table&amp;) =3D default;</div><div>&nbsp; constexpr en=
um_table(enum_table&amp;&amp;) =3D default;</div><div><div>&nbsp; constexpr=
 enum_table&amp; operator=3D(const enum_table&amp;) =3D default;</div><div>=
&nbsp; constexpr enum_table&amp; operator=3D(enum_table&amp;&amp;) =3D defa=
ult;</div></div><div><br></div><div>&nbsp; constexpr const T&amp; operator[=
E tag] const;</div><div>&nbsp; constexpr bool lookup(const T&amp; value, E&=
amp; tag) const;</div><div>&nbsp; constexpr bool lookup(T&amp;&amp; value, =
E&amp; tag) const;</div><div>&nbsp; constexpr size_t size() const;</div><di=
v><br></div><div>&nbsp; class iterator : std::bidirectional_iterator&lt;<wb=
r>std::pair&lt;E, const T&amp;&gt;&gt; {};</div><div>&nbsp; class reverse_i=
terator;</div><div>&nbsp;&nbsp;</div><div>&nbsp; constexpr iterator begin()=
;</div><div>&nbsp; constexpr iterator end();</div><div><div>&nbsp; constexp=
r reverse_iterator rbegin();</div><div>&nbsp; constexpr reverse_iterator re=
nd();</div><div><br></div><div>&nbsp; constexpr iterator find(E tag);</div>=
<div>&nbsp; template &lt;typename Comparable&gt;</div><div>&nbsp; constexpr=
 iterator find(Comparable&amp;&amp; c); //lookup using CMP(const T&amp;, C&=
amp;&amp;) or CMP(const T&amp;, const C&amp;) using perfect forwarding</div=
><div>&nbsp; constexpr iterator find(T&amp;&amp; value); //lookup using CMP=
()</div>};</div><div><br></div><div>template &lt;typename E&gt;</div><div>u=
sing enum_strtable =3D enum_table&lt;E, const char*, [](const char* l, cons=
t char* r){ return strcmp(l, r) =3D=3D 0; }&gt;;</div><div><br></div><div><=
br></div><div>//Usage</div><div>enum Color {<br>&nbsp; kRed,</div><div>&nbs=
p; kGreen,</div><div>&nbsp; kBlue</div><div>};</div><div><br></div><div>//C=
ould be place in binary .rodata section.</div><div>constexpr const enumstr_=
table&lt;Color&gt; color_tbl =3D { "Red", "Blue", "Green" };</div><div><br>=
</div><div>assert(!strcmp(color_tbl[kRed]<wbr>, "Red"));</div><div>assert(c=
olor_tbl.find("Red") !=3D color_tbl.end());</div><div><br></div><div>I real=
ly want this for ubound, and loop(), and runtime string tables but while we=
're at it, there's a lot of cool stuff we could add.</div><div>Rationale he=
re:</div><div><a href=3D"https://groups.google.com/forum/#!searchin/comp.la=
ng.c$2B$2B.moderated/enum/comp.lang.c++.moderated/RpUiU9utY48/N-oUkAo5oIoJ"=
 target=3D"_blank" onmousedown=3D"this.href=3D'https://groups.google.com/fo=
rum/#!searchin/comp.lang.c$2B$2B.moderated/enum/comp.lang.c++.moderated/RpU=
iU9utY48/N-oUkAo5oIoJ';return true;" onclick=3D"this.href=3D'https://groups=
..google.com/forum/#!searchin/comp.lang.c$2B$2B.moderated/enum/comp.lang.c++=
..moderated/RpUiU9utY48/N-oUkAo5oIoJ';return true;">https://groups.google.co=
m/<wbr>forum/#!searchin/comp.lang.c$<wbr>2B$2B.moderated/enum/comp.<wbr>lan=
g.c++.moderated/<wbr>RpUiU9utY48/N-oUkAo5oIoJ</a><br></div><div><br></div><=
div>Other extensions I'd love to see:</div><div>* enum bitmasks as a real t=
ype, easy and expressive to declare, strict rules about logical operator co=
mparisons. Only the tags in the enum can use binary logical operations with=
 one another.</div><div>* concepts in the enum declaration to enforce restr=
ictions (is_contiguous, min =3D=3D 0, etc..)</div><div><br></div><div><br><=
/div></div></blockquote></div></blockquote></div></div></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_26_24717104.1389452390106--

.


Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Sat, 11 Jan 2014 20:39:50 -0800 (PST)
Raw View
------=_Part_1433_17809189.1389501590050
Content-Type: text/plain; charset=ISO-8859-1

Could you please review N3815
(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3815.html) and
confirm that you can implement your enum_traits and enum_table class as a
pure library feature on top of the three provided type traits, and that the
solution would be as efficient as if the compiler did it for you?

If you are unsure or think you have a feature you want that could not be
implemented on top of the N3815 type traits as an efficient pure library
feature, could you please point it out?

Our current plan is to standardize N3815 in the Library Fundamentals TS as
a minmal complete interface that enables library / framework authors to
provide all this functionality that you want.

From a review of your enum_traits and enum_table class I believe that this
is indeed the case - that both could all be built efficiently as a pure
library solution on top of the N3815.  Could you see if you agree.

Thanks,
Andrew.



On Saturday, January 11, 2014 7:47:48 AM UTC+1, fmatth...@gmail.com wrote:
>
> Enums are one of my favorite tools for efficently labeling collections,
> but we need to be able to query more information about them.
>
> I'd like to suggest some form of enum traits.
>
> template <typename E>
> struct enum_traits<E> {
>   static_assert(is_enum<E>::value, "Only valid for enums!");
>
>   typedef /* underlying type */ value_type;
>   static constexpr const value_type min = /* minimum value of enum */
>   static constexpr const value_type max = /* maximum value of enum */
>   static constexpr const value_type ubound = /* maximum value of enum+1.
> Not present (does not compile if queried) if max ==
> numeric_limits<value_type>::max(). (Note: this is the most useful value)*/
>
>   static constexpr const size_t count = /* Number of enum tags */
>   static constexpr const size_t distinct = /* Number of enum tags with
> distinct values */
>   static constexpr const bool is_contiguious = /* true if enum values are
> contiguous */
>   static constexpr const bool is_regular = is_contiguous && min ==
> value_type(0);
>   static constexpr const bool has_zero = /* true if zero is an enum value
> */
>   static constexpr const bool has_postive = /* true if at least one enum
> value is positive */
>   static constexpr const bool all_postive = /* true if all enum values are
> positive */
>   static constexpr const bool has_negative = /* true if at least one enum
> value is negative */
>   static constexpr const bool all_negative = /* true if all enum values
> are negative */
>
> //Utilities to enable foreach, compiler generated
>   class iterator : public std::bidirectional_iterator<E> {
>     public:
>       E operator*();
>       //iterator stuff, operator++ goes to next enum value in operator<()
> order.
>   };
>   class reverse_iterator;
>   struct range {
>
>     iterator begin();
>     iterator end();
>
>     reverse_iterator rbegin();
>     reverse_iterator rend();
>   };
>
>   range<E> loop();
> };
>
> //foreach loop over enum values
> for(auto e : enum_traits<E>::loop()) {
> };
>
> //Create tables keyed by enums, standard library component
> template <typename E, typename T, typename CMP = std::equal_to>
> class enum_table {
>   //static asserts if li.size() != enum_traits<E>::distinct;
>   constexpr enum_table(std::initializer_list<T> li);
>   constexpr enum_table(const enum_table&) = default;
>   constexpr enum_table(enum_table&&) = default;
>   constexpr enum_table& operator=(const enum_table&) = default;
>   constexpr enum_table& operator=(enum_table&&) = default;
>
>   constexpr const T& operator[E tag] const;
>   constexpr bool lookup(const T& value, E& tag) const;
>   constexpr bool lookup(T&& value, E& tag) const;
>   constexpr size_t size() const;
>
>   class iterator : std::bidirectional_iterator<std::pair<E, const T&>> {};
>   class reverse_iterator;
>
>   constexpr iterator begin();
>   constexpr iterator end();
>   constexpr reverse_iterator rbegin();
>   constexpr reverse_iterator rend();
>
>   constexpr iterator find(E tag);
>   template <typename Comparable>
>   constexpr iterator find(Comparable&& c); //lookup using CMP(const T&,
> C&&) or CMP(const T&, const C&) using perfect forwarding
>   constexpr iterator find(T&& value); //lookup using CMP()
> };
>
> template <typename E>
> using enum_strtable = enum_table<E, const char*, [](const char* l, const
> char* r){ return strcmp(l, r) == 0; }>;
>
>
> //Usage
> enum Color {
>   kRed,
>   kGreen,
>   kBlue
> };
>
> //Could be place in binary .rodata section.
> constexpr const enumstr_table<Color> color_tbl = { "Red", "Blue", "Green"
> };
>
> assert(!strcmp(color_tbl[kRed], "Red"));
> assert(color_tbl.find("Red") != color_tbl.end());
>
> I really want this for ubound, and loop(), and runtime string tables but
> while we're at it, there's a lot of cool stuff we could add.
> Rationale here:
>
> https://groups.google.com/forum/#!searchin/comp.lang.c$2B$2B.moderated/enum/comp.lang.c++.moderated/RpUiU9utY48/N-oUkAo5oIoJ
>
> Other extensions I'd love to see:
> * enum bitmasks as a real type, easy and expressive to declare, strict
> rules about logical operator comparisons. Only the tags in the enum can use
> binary logical operations with one another.
> * concepts in the enum declaration to enforce restrictions (is_contiguous,
> min == 0, etc..)
>
>
>

--

---
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_1433_17809189.1389501590050
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Could you please review N3815 (http://www.open-std.org/jtc=
1/sc22/wg21/docs/papers/2013/n3815.html)&nbsp;and confirm that you can impl=
ement your enum_traits and enum_table class as a pure library feature on to=
p of the three provided type traits, and that the solution would be as effi=
cient as if the compiler did it for you?<div><br></div><div>If you are unsu=
re or think you have a feature you want that could not be implemented on to=
p of the N3815 type traits as an efficient pure library feature, could you =
please point it out?</div><div><br></div><div>Our current plan is to standa=
rdize N3815 in the Library Fundamentals TS as a minmal complete interface t=
hat enables library / framework authors to provide all this functionality t=
hat you want.</div><div><br></div><div>From a review of your enum_traits an=
d enum_table class I believe that this is indeed the case - that both could=
 all be built efficiently as a pure library solution on top of the N3815. &=
nbsp;Could you see if you agree.<br><br>Thanks,</div><div>Andrew.</div><div=
><br><br><br>On Saturday, January 11, 2014 7:47:48 AM UTC+1, fmatth...@gmai=
l.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">E=
nums are one of my favorite tools for efficently labeling collections, but =
we need to be able to query more information about them.<div><br></div><div=
>I'd like to suggest some form of enum traits.&nbsp;</div><div><br></div><d=
iv>template &lt;typename E&gt;</div><div>struct enum_traits&lt;E&gt; {</div=
><div>&nbsp; static_assert(is_enum&lt;E&gt;::<wbr>value, "Only valid for en=
ums!");</div><div>&nbsp;&nbsp;</div><div>&nbsp; typedef /* underlying type =
*/ value_type;</div><div>&nbsp; static constexpr const value_type min =3D /=
* minimum value of enum */</div><div>&nbsp; static constexpr const value_ty=
pe max =3D /* maximum value of enum */</div><div>&nbsp; static constexpr co=
nst value_type ubound =3D /* maximum value of enum+1. Not present (does not=
 compile if queried) if max =3D=3D numeric_limits&lt;value_type&gt;::<wbr>m=
ax(). (Note: this is the most useful value)*/</div><div><br></div><div>&nbs=
p; static constexpr const size_t count =3D /* Number of enum tags */</div><=
div>&nbsp; static constexpr const size_t distinct =3D /* Number of enum tag=
s with distinct values */&nbsp;</div><div>&nbsp; static constexpr const boo=
l is_contiguious =3D /* true if enum values are contiguous */</div><div>&nb=
sp; static constexpr const bool is_regular =3D is_contiguous &amp;&amp; min=
 =3D=3D value_type(0);</div><div>&nbsp; static constexpr const bool has_zer=
o =3D /* true if zero is an enum value */</div><div>&nbsp; static constexpr=
 const bool has_postive =3D /* true if at least one enum value is positive =
*/</div><div>&nbsp; static constexpr const bool all_postive =3D /* true if =
all enum values are positive */</div><div>&nbsp; static constexpr const boo=
l has_negative =3D /* true if at least one enum value is negative */</div><=
div>&nbsp; static constexpr const bool all_negative =3D /* true if all enum=
 values are negative */</div><div><br></div><div>//Utilities to enable fore=
ach, compiler generated</div><div>&nbsp; class iterator : public std::bidir=
ectional_iterator&lt;E&gt; {</div><div>&nbsp; &nbsp; public:</div><div>&nbs=
p; &nbsp; &nbsp; E operator*();</div><div>&nbsp; &nbsp; &nbsp; //iterator s=
tuff, operator++ goes to next enum value in operator&lt;() order.</div><div=
>&nbsp; };</div><div>&nbsp; class reverse_iterator;</div><div>&nbsp; struct=
 range {</div><div><br></div><div>&nbsp; &nbsp; iterator begin();</div><div=
>&nbsp; &nbsp; iterator end();</div><div><br></div><div>&nbsp; &nbsp; rever=
se_iterator rbegin();</div><div>&nbsp; &nbsp; reverse_iterator rend();<br>&=
nbsp; };</div><div><br></div><div>&nbsp; range&lt;E&gt; loop();</div><div>}=
;</div><div><br></div><div>//foreach loop over enum values</div><div>for(au=
to e : enum_traits&lt;E&gt;::loop()) {<br>};</div><div><br></div><div>//Cre=
ate tables keyed by enums, standard library component</div><div>template &l=
t;typename E, typename T, typename CMP =3D std::equal_to&gt;</div><div>clas=
s enum_table {</div><div>&nbsp; //static asserts if li.size() !=3D enum_tra=
its&lt;E&gt;::distinct;</div><div>&nbsp; constexpr enum_table(std::initiali=
zer_<wbr>list&lt;T&gt; li);</div><div>&nbsp; constexpr enum_table(const enu=
m_table&amp;) =3D default;</div><div>&nbsp; constexpr enum_table(enum_table=
&amp;&amp;) =3D default;</div><div><div>&nbsp; constexpr enum_table&amp; op=
erator=3D(const enum_table&amp;) =3D default;</div><div>&nbsp; constexpr en=
um_table&amp; operator=3D(enum_table&amp;&amp;) =3D default;</div></div><di=
v><br></div><div>&nbsp; constexpr const T&amp; operator[E tag] const;</div>=
<div>&nbsp; constexpr bool lookup(const T&amp; value, E&amp; tag) const;</d=
iv><div>&nbsp; constexpr bool lookup(T&amp;&amp; value, E&amp; tag) const;<=
/div><div>&nbsp; constexpr size_t size() const;</div><div><br></div><div>&n=
bsp; class iterator : std::bidirectional_iterator&lt;<wbr>std::pair&lt;E, c=
onst T&amp;&gt;&gt; {};</div><div>&nbsp; class reverse_iterator;</div><div>=
&nbsp;&nbsp;</div><div>&nbsp; constexpr iterator begin();</div><div>&nbsp; =
constexpr iterator end();</div><div><div>&nbsp; constexpr reverse_iterator =
rbegin();</div><div>&nbsp; constexpr reverse_iterator rend();</div><div><br=
></div><div>&nbsp; constexpr iterator find(E tag);</div><div>&nbsp; templat=
e &lt;typename Comparable&gt;</div><div>&nbsp; constexpr iterator find(Comp=
arable&amp;&amp; c); //lookup using CMP(const T&amp;, C&amp;&amp;) or CMP(c=
onst T&amp;, const C&amp;) using perfect forwarding</div><div>&nbsp; conste=
xpr iterator find(T&amp;&amp; value); //lookup using CMP()</div>};</div><di=
v><br></div><div>template &lt;typename E&gt;</div><div>using enum_strtable =
=3D enum_table&lt;E, const char*, [](const char* l, const char* r){ return =
strcmp(l, r) =3D=3D 0; }&gt;;</div><div><br></div><div><br></div><div>//Usa=
ge</div><div>enum Color {<br>&nbsp; kRed,</div><div>&nbsp; kGreen,</div><di=
v>&nbsp; kBlue</div><div>};</div><div><br></div><div>//Could be place in bi=
nary .rodata section.</div><div>constexpr const enumstr_table&lt;Color&gt; =
color_tbl =3D { "Red", "Blue", "Green" };</div><div><br></div><div>assert(!=
strcmp(color_tbl[kRed]<wbr>, "Red"));</div><div>assert(color_tbl.find("Red"=
) !=3D color_tbl.end());</div><div><br></div><div>I really want this for ub=
ound, and loop(), and runtime string tables but while we're at it, there's =
a lot of cool stuff we could add.</div><div>Rationale here:</div><div><a hr=
ef=3D"https://groups.google.com/forum/#!searchin/comp.lang.c$2B$2B.moderate=
d/enum/comp.lang.c++.moderated/RpUiU9utY48/N-oUkAo5oIoJ" target=3D"_blank" =
onmousedown=3D"this.href=3D'https://groups.google.com/forum/#!searchin/comp=
..lang.c$2B$2B.moderated/enum/comp.lang.c++.moderated/RpUiU9utY48/N-oUkAo5oI=
oJ';return true;" onclick=3D"this.href=3D'https://groups.google.com/forum/#=
!searchin/comp.lang.c$2B$2B.moderated/enum/comp.lang.c++.moderated/RpUiU9ut=
Y48/N-oUkAo5oIoJ';return true;">https://groups.google.com/<wbr>forum/#!sear=
chin/comp.lang.c$<wbr>2B$2B.moderated/enum/comp.<wbr>lang.c++.moderated/<wb=
r>RpUiU9utY48/N-oUkAo5oIoJ</a><br></div><div><br></div><div>Other extension=
s I'd love to see:</div><div>* enum bitmasks as a real type, easy and expre=
ssive to declare, strict rules about logical operator comparisons. Only the=
 tags in the enum can use binary logical operations with one another.</div>=
<div>* concepts in the enum declaration to enforce restrictions (is_contigu=
ous, min =3D=3D 0, etc..)</div><div><br></div><div><br></div></div></blockq=
uote></div></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_1433_17809189.1389501590050--

.


Author: fmatthew5876@gmail.com
Date: Sat, 11 Jan 2014 21:16:52 -0800 (PST)
Raw View
------=_Part_1024_2866559.1389503812298
Content-Type: text/plain; charset=ISO-8859-1

Sure, is there a working implementation of your proposal? I don't have a
lot of free time so it will be slow, but I can take a look. If so, I might
like to help work on the library features that come after your proposal.

The list I made is a general sketch of some of the things I think might be
immediatly useful. Many of these I already do manually using crude
interfaces now. It will take some time to come up with a solid library
design with a correctly chosen and designed features.



On Saturday, January 11, 2014 11:39:50 PM UTC-5, Andrew Tomazos wrote:
>
> Could you please review N3815 (
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3815.html) and
> confirm that you can implement your enum_traits and enum_table class as a
> pure library feature on top of the three provided type traits, and that the
> solution would be as efficient as if the compiler did it for you?
>
> If you are unsure or think you have a feature you want that could not be
> implemented on top of the N3815 type traits as an efficient pure library
> feature, could you please point it out?
>
> Our current plan is to standardize N3815 in the Library Fundamentals TS as
> a minmal complete interface that enables library / framework authors to
> provide all this functionality that you want.
>
> From a review of your enum_traits and enum_table class I believe that this
> is indeed the case - that both could all be built efficiently as a pure
> library solution on top of the N3815.  Could you see if you agree.
>
> Thanks,
> Andrew.
>
>
>
> On Saturday, January 11, 2014 7:47:48 AM UTC+1, fmatth...@gmail.com wrote:
>>
>> Enums are one of my favorite tools for efficently labeling collections,
>> but we need to be able to query more information about them.
>>
>> I'd like to suggest some form of enum traits.
>>
>> template <typename E>
>> struct enum_traits<E> {
>>   static_assert(is_enum<E>::value, "Only valid for enums!");
>>
>>   typedef /* underlying type */ value_type;
>>   static constexpr const value_type min = /* minimum value of enum */
>>   static constexpr const value_type max = /* maximum value of enum */
>>   static constexpr const value_type ubound = /* maximum value of enum+1.
>> Not present (does not compile if queried) if max ==
>> numeric_limits<value_type>::max(). (Note: this is the most useful value)*/
>>
>>   static constexpr const size_t count = /* Number of enum tags */
>>   static constexpr const size_t distinct = /* Number of enum tags with
>> distinct values */
>>   static constexpr const bool is_contiguious = /* true if enum values are
>> contiguous */
>>   static constexpr const bool is_regular = is_contiguous && min ==
>> value_type(0);
>>   static constexpr const bool has_zero = /* true if zero is an enum value
>> */
>>   static constexpr const bool has_postive = /* true if at least one enum
>> value is positive */
>>   static constexpr const bool all_postive = /* true if all enum values
>> are positive */
>>   static constexpr const bool has_negative = /* true if at least one enum
>> value is negative */
>>   static constexpr const bool all_negative = /* true if all enum values
>> are negative */
>>
>> //Utilities to enable foreach, compiler generated
>>   class iterator : public std::bidirectional_iterator<E> {
>>     public:
>>       E operator*();
>>       //iterator stuff, operator++ goes to next enum value in operator<()
>> order.
>>   };
>>   class reverse_iterator;
>>   struct range {
>>
>>     iterator begin();
>>     iterator end();
>>
>>     reverse_iterator rbegin();
>>     reverse_iterator rend();
>>   };
>>
>>   range<E> loop();
>> };
>>
>> //foreach loop over enum values
>> for(auto e : enum_traits<E>::loop()) {
>> };
>>
>> //Create tables keyed by enums, standard library component
>> template <typename E, typename T, typename CMP = std::equal_to>
>> class enum_table {
>>   //static asserts if li.size() != enum_traits<E>::distinct;
>>   constexpr enum_table(std::initializer_list<T> li);
>>   constexpr enum_table(const enum_table&) = default;
>>   constexpr enum_table(enum_table&&) = default;
>>   constexpr enum_table& operator=(const enum_table&) = default;
>>   constexpr enum_table& operator=(enum_table&&) = default;
>>
>>   constexpr const T& operator[E tag] const;
>>   constexpr bool lookup(const T& value, E& tag) const;
>>   constexpr bool lookup(T&& value, E& tag) const;
>>   constexpr size_t size() const;
>>
>>   class iterator : std::bidirectional_iterator<std::pair<E, const T&>> {};
>>   class reverse_iterator;
>>
>>   constexpr iterator begin();
>>   constexpr iterator end();
>>   constexpr reverse_iterator rbegin();
>>   constexpr reverse_iterator rend();
>>
>>   constexpr iterator find(E tag);
>>   template <typename Comparable>
>>   constexpr iterator find(Comparable&& c); //lookup using CMP(const T&,
>> C&&) or CMP(const T&, const C&) using perfect forwarding
>>   constexpr iterator find(T&& value); //lookup using CMP()
>> };
>>
>> template <typename E>
>> using enum_strtable = enum_table<E, const char*, [](const char* l, const
>> char* r){ return strcmp(l, r) == 0; }>;
>>
>>
>> //Usage
>> enum Color {
>>   kRed,
>>   kGreen,
>>   kBlue
>> };
>>
>> //Could be place in binary .rodata section.
>> constexpr const enumstr_table<Color> color_tbl = { "Red", "Blue", "Green"
>> };
>>
>> assert(!strcmp(color_tbl[kRed], "Red"));
>> assert(color_tbl.find("Red") != color_tbl.end());
>>
>> I really want this for ubound, and loop(), and runtime string tables but
>> while we're at it, there's a lot of cool stuff we could add.
>> Rationale here:
>>
>> https://groups.google.com/forum/#!searchin/comp.lang.c$2B$2B.moderated/enum/comp.lang.c++.moderated/RpUiU9utY48/N-oUkAo5oIoJ
>>
>> Other extensions I'd love to see:
>> * enum bitmasks as a real type, easy and expressive to declare, strict
>> rules about logical operator comparisons. Only the tags in the enum can use
>> binary logical operations with one another.
>> * concepts in the enum declaration to enforce restrictions
>> (is_contiguous, min == 0, etc..)
>>
>>
>>

--

---
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_1024_2866559.1389503812298
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Sure, is there a working implementation of your proposal? =
I don't have a lot of free time so it will be slow, but I can take a look. =
If so, I might like to help work on the library features that come after yo=
ur proposal.&nbsp;<div><br></div><div>The list I made is a general sketch o=
f some of the things I think might be immediatly useful. Many of these I al=
ready do manually using crude interfaces now. It will take some time to com=
e up with a solid library design with a correctly chosen and designed featu=
res.</div><div><br></div><div><br><br>On Saturday, January 11, 2014 11:39:5=
0 PM UTC-5, Andrew Tomazos 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">Could you please review N3815 (<a href=3D"http://www.op=
en-std.org/jtc1/sc22/wg21/docs/papers/2013/n3815.html" target=3D"_blank" on=
mousedown=3D"this.href=3D'http://www.google.com/url?q\75http%3A%2F%2Fwww.op=
en-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2013%2Fn3815.html\46sa\75=
D\46sntz\0751\46usg\75AFQjCNHwe7liqoidkU5rvKFSWklGuTd4gw';return true;" onc=
lick=3D"this.href=3D'http://www.google.com/url?q\75http%3A%2F%2Fwww.open-st=
d.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2013%2Fn3815.html\46sa\75D\46s=
ntz\0751\46usg\75AFQjCNHwe7liqoidkU5rvKFSWklGuTd4gw';return true;">http://w=
ww.open-std.org/jtc1/<wbr>sc22/wg21/docs/papers/2013/<wbr>n3815.html</a>)&n=
bsp;and confirm that you can implement your enum_traits and enum_table clas=
s as a pure library feature on top of the three provided type traits, and t=
hat the solution would be as efficient as if the compiler did it for you?<d=
iv><br></div><div>If you are unsure or think you have a feature you want th=
at could not be implemented on top of the N3815 type traits as an efficient=
 pure library feature, could you please point it out?</div><div><br></div><=
div>Our current plan is to standardize N3815 in the Library Fundamentals TS=
 as a minmal complete interface that enables library / framework authors to=
 provide all this functionality that you want.</div><div><br></div><div>Fro=
m a review of your enum_traits and enum_table class I believe that this is =
indeed the case - that both could all be built efficiently as a pure librar=
y solution on top of the N3815. &nbsp;Could you see if you agree.<br><br>Th=
anks,</div><div>Andrew.</div><div><br><br><br>On Saturday, January 11, 2014=
 7:47:48 AM UTC+1, <a>fmatth...@gmail.com</a> wrote:<blockquote class=3D"gm=
ail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;p=
adding-left:1ex"><div dir=3D"ltr">Enums are one of my favorite tools for ef=
ficently labeling collections, but we need to be able to query more informa=
tion about them.<div><br></div><div>I'd like to suggest some form of enum t=
raits.&nbsp;</div><div><br></div><div>template &lt;typename E&gt;</div><div=
>struct enum_traits&lt;E&gt; {</div><div>&nbsp; static_assert(is_enum&lt;E&=
gt;::<wbr>value, "Only valid for enums!");</div><div>&nbsp;&nbsp;</div><div=
>&nbsp; typedef /* underlying type */ value_type;</div><div>&nbsp; static c=
onstexpr const value_type min =3D /* minimum value of enum */</div><div>&nb=
sp; static constexpr const value_type max =3D /* maximum value of enum */</=
div><div>&nbsp; static constexpr const value_type ubound =3D /* maximum val=
ue of enum+1. Not present (does not compile if queried) if max =3D=3D numer=
ic_limits&lt;value_type&gt;::<wbr>max(). (Note: this is the most useful val=
ue)*/</div><div><br></div><div>&nbsp; static constexpr const size_t count =
=3D /* Number of enum tags */</div><div>&nbsp; static constexpr const size_=
t distinct =3D /* Number of enum tags with distinct values */&nbsp;</div><d=
iv>&nbsp; static constexpr const bool is_contiguious =3D /* true if enum va=
lues are contiguous */</div><div>&nbsp; static constexpr const bool is_regu=
lar =3D is_contiguous &amp;&amp; min =3D=3D value_type(0);</div><div>&nbsp;=
 static constexpr const bool has_zero =3D /* true if zero is an enum value =
*/</div><div>&nbsp; static constexpr const bool has_postive =3D /* true if =
at least one enum value is positive */</div><div>&nbsp; static constexpr co=
nst bool all_postive =3D /* true if all enum values are positive */</div><d=
iv>&nbsp; static constexpr const bool has_negative =3D /* true if at least =
one enum value is negative */</div><div>&nbsp; static constexpr const bool =
all_negative =3D /* true if all enum values are negative */</div><div><br><=
/div><div>//Utilities to enable foreach, compiler generated</div><div>&nbsp=
; class iterator : public std::bidirectional_iterator&lt;E&gt; {</div><div>=
&nbsp; &nbsp; public:</div><div>&nbsp; &nbsp; &nbsp; E operator*();</div><d=
iv>&nbsp; &nbsp; &nbsp; //iterator stuff, operator++ goes to next enum valu=
e in operator&lt;() order.</div><div>&nbsp; };</div><div>&nbsp; class rever=
se_iterator;</div><div>&nbsp; struct range {</div><div><br></div><div>&nbsp=
; &nbsp; iterator begin();</div><div>&nbsp; &nbsp; iterator end();</div><di=
v><br></div><div>&nbsp; &nbsp; reverse_iterator rbegin();</div><div>&nbsp; =
&nbsp; reverse_iterator rend();<br>&nbsp; };</div><div><br></div><div>&nbsp=
; range&lt;E&gt; loop();</div><div>};</div><div><br></div><div>//foreach lo=
op over enum values</div><div>for(auto e : enum_traits&lt;E&gt;::loop()) {<=
br>};</div><div><br></div><div>//Create tables keyed by enums, standard lib=
rary component</div><div>template &lt;typename E, typename T, typename CMP =
=3D std::equal_to&gt;</div><div>class enum_table {</div><div>&nbsp; //stati=
c asserts if li.size() !=3D enum_traits&lt;E&gt;::distinct;</div><div>&nbsp=
; constexpr enum_table(std::initializer_<wbr>list&lt;T&gt; li);</div><div>&=
nbsp; constexpr enum_table(const enum_table&amp;) =3D default;</div><div>&n=
bsp; constexpr enum_table(enum_table&amp;&amp;) =3D default;</div><div><div=
>&nbsp; constexpr enum_table&amp; operator=3D(const enum_table&amp;) =3D de=
fault;</div><div>&nbsp; constexpr enum_table&amp; operator=3D(enum_table&am=
p;&amp;) =3D default;</div></div><div><br></div><div>&nbsp; constexpr const=
 T&amp; operator[E tag] const;</div><div>&nbsp; constexpr bool lookup(const=
 T&amp; value, E&amp; tag) const;</div><div>&nbsp; constexpr bool lookup(T&=
amp;&amp; value, E&amp; tag) const;</div><div>&nbsp; constexpr size_t size(=
) const;</div><div><br></div><div>&nbsp; class iterator : std::bidirectiona=
l_iterator&lt;<wbr>std::pair&lt;E, const T&amp;&gt;&gt; {};</div><div>&nbsp=
; class reverse_iterator;</div><div>&nbsp;&nbsp;</div><div>&nbsp; constexpr=
 iterator begin();</div><div>&nbsp; constexpr iterator end();</div><div><di=
v>&nbsp; constexpr reverse_iterator rbegin();</div><div>&nbsp; constexpr re=
verse_iterator rend();</div><div><br></div><div>&nbsp; constexpr iterator f=
ind(E tag);</div><div>&nbsp; template &lt;typename Comparable&gt;</div><div=
>&nbsp; constexpr iterator find(Comparable&amp;&amp; c); //lookup using CMP=
(const T&amp;, C&amp;&amp;) or CMP(const T&amp;, const C&amp;) using perfec=
t forwarding</div><div>&nbsp; constexpr iterator find(T&amp;&amp; value); /=
/lookup using CMP()</div>};</div><div><br></div><div>template &lt;typename =
E&gt;</div><div>using enum_strtable =3D enum_table&lt;E, const char*, [](co=
nst char* l, const char* r){ return strcmp(l, r) =3D=3D 0; }&gt;;</div><div=
><br></div><div><br></div><div>//Usage</div><div>enum Color {<br>&nbsp; kRe=
d,</div><div>&nbsp; kGreen,</div><div>&nbsp; kBlue</div><div>};</div><div><=
br></div><div>//Could be place in binary .rodata section.</div><div>constex=
pr const enumstr_table&lt;Color&gt; color_tbl =3D { "Red", "Blue", "Green" =
};</div><div><br></div><div>assert(!strcmp(color_tbl[kRed]<wbr>, "Red"));</=
div><div>assert(color_tbl.find("Red") !=3D color_tbl.end());</div><div><br>=
</div><div>I really want this for ubound, and loop(), and runtime string ta=
bles but while we're at it, there's a lot of cool stuff we could add.</div>=
<div>Rationale here:</div><div><a href=3D"https://groups.google.com/forum/#=
!searchin/comp.lang.c$2B$2B.moderated/enum/comp.lang.c++.moderated/RpUiU9ut=
Y48/N-oUkAo5oIoJ" target=3D"_blank" onmousedown=3D"this.href=3D'https://gro=
ups.google.com/forum/#!searchin/comp.lang.c$2B$2B.moderated/enum/comp.lang.=
c++.moderated/RpUiU9utY48/N-oUkAo5oIoJ';return true;" onclick=3D"this.href=
=3D'https://groups.google.com/forum/#!searchin/comp.lang.c$2B$2B.moderated/=
enum/comp.lang.c++.moderated/RpUiU9utY48/N-oUkAo5oIoJ';return true;">https:=
//groups.google.com/<wbr>forum/#!searchin/comp.lang.c$<wbr>2B$2B.moderated/=
enum/comp.<wbr>lang.c++.moderated/<wbr>RpUiU9utY48/N-oUkAo5oIoJ</a><br></di=
v><div><br></div><div>Other extensions I'd love to see:</div><div>* enum bi=
tmasks as a real type, easy and expressive to declare, strict rules about l=
ogical operator comparisons. Only the tags in the enum can use binary logic=
al operations with one another.</div><div>* concepts in the enum declaratio=
n to enforce restrictions (is_contiguous, min =3D=3D 0, etc..)</div><div><b=
r></div><div><br></div></div></blockquote></div></div></blockquote></div></=
div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_1024_2866559.1389503812298--

.


Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Sat, 11 Jan 2014 23:01:12 -0800 (PST)
Raw View
------=_Part_659_29162198.1389510072208
Content-Type: text/plain; charset=ISO-8859-1

So, first yes, my co-author Christian has written a reference
implementation that contains a superset of the N3815 proposed three
property queries.  You will find the link on the bottom of N3815.  This has
been forked and extended by Remotion (linked previously in this thread).

But before you go diving into that and compiling custom implementation, the
three traits are really simple to understand and to mock up by hand with an
ordinary compiler:

First recall the three property queries are:

    enumerator_list_size<E> is the number of enumerators in the enumeration
E
    enumerator_value<E,I> is a value of type E that is the I'th enumerator
in declared order.
    enumerator_identifier<E,I> is a string literal with the identifier of
the I'th enumerator in declared order.

So you can mock them up for experimentation "by hand" without compiler
changes as follows:

First declare but don't define the three N3815 primaries...

    template<typename E> struct enumerator_list_size;
    template<typename E, size_t I> struct enumerator_value;
    template<typename E, size_t I> struct enumerator_identifier;

Then for each enumeration type in your test program, for example...

    enum foo
    {
        bar,
        Baz,
        Qux = 42,
        Quux = 42,
    };

....manually define a set of specializations by hand as follows...

    template<> struct enumerator_list_size<foo> { static constexpr size_t
value = 4; };

    template<> struct enumerator_value<foo,0> { static constexpr foo value
= bar; };
    template<> struct enumerator_value<foo,1> { static constexpr foo value
= Baz; };
    template<> struct enumerator_value<foo,2> { static constexpr foo value
= Qux; };
    template<> struct enumerator_value<foo,3> { static constexpr foo value
= Quux; };

    template<> struct enumerator_identifier<foo,0> { static constexpr char
value[4] = u8"bar"; };
    template<> struct enumerator_identifier<foo,1> { static constexpr char
value[4] = u8"Baz"; };
    template<> struct enumerator_identifier<foo,2> { static constexpr char
value[4] = u8"Qux"; };
    template<> struct enumerator_identifier<foo,3> { static constexpr char
value[5] = u8"Quux"; };

    constexpr char enumerator_identifier<foo,0>::value[];
    constexpr char enumerator_identifier<foo,1>::value[];
    constexpr char enumerator_identifier<foo,2>::value[];
    constexpr char enumerator_identifier<foo,3>::value[];

(The effect of N3815 is that these hand-written specializations will be
done automatically for you by the compiler when you use them.)

Here is a complete self-contained compiling program with the above
integrated together you can copy and paste plus some tests:

    #include <cassert>
    #include <cstddef>
    #include <string.h>

    // N3815 primaries
    template<typename E> struct enumerator_list_size;
    template<typename E, size_t I> struct enumerator_value;
    template<typename E, size_t I> struct enumerator_identifier;

    // your enumeration
    enum foo
    {
        bar,
        Baz,
        Qux = 42,
        Quux = 42,
    };

    // define these specializations by hand:
    template<> struct enumerator_list_size<foo> { static constexpr size_t
value = 4; };

    template<> struct enumerator_value<foo,0> { static constexpr foo value
= bar; };
    template<> struct enumerator_value<foo,1> { static constexpr foo value
= Baz; };
    template<> struct enumerator_value<foo,2> { static constexpr foo value
= Qux; };
    template<> struct enumerator_value<foo,3> { static constexpr foo value
= Quux; };

    template<> struct enumerator_identifier<foo,0> { static constexpr char
value[4] = u8"bar"; };
    template<> struct enumerator_identifier<foo,1> { static constexpr char
value[4] = u8"Baz"; };
    template<> struct enumerator_identifier<foo,2> { static constexpr char
value[4] = u8"Qux"; };
    template<> struct enumerator_identifier<foo,3> { static constexpr char
value[5] = u8"Quux"; };

    constexpr char enumerator_identifier<foo,0>::value[];
    constexpr char enumerator_identifier<foo,1>::value[];
    constexpr char enumerator_identifier<foo,2>::value[];
    constexpr char enumerator_identifier<foo,3>::value[];

    // test they work:
    int main()
    {
        static_assert(enumerator_list_size<foo>::value == 4, "");

        assert(strcmp(enumerator_identifier<foo,0>::value, u8"bar") == 0);
        assert(strcmp(enumerator_identifier<foo,1>::value, u8"Baz") == 0);
        assert(strcmp(enumerator_identifier<foo,2>::value, u8"Qux") == 0);
        assert(strcmp(enumerator_identifier<foo,3>::value, u8"Quux") == 0);

        static_assert(enumerator_value<foo,0>::value == bar, "");
        static_assert(enumerator_value<foo,1>::value == Baz, "");
        static_assert(enumerator_value<foo,2>::value == Qux, "");
        static_assert(enumerator_value<foo,3>::value == Quux, "");

        constexpr const char* str = enumerator_identifier<foo,0>::value;
        static_assert(str[0] == 'b', "");
        static_assert(str[1] == 'a', "");
        static_assert(str[2] == 'r', "");
        static_assert(str[3] == '\0', "");
    }

Enjoy,
Andrew.


On Sunday, January 12, 2014 6:16:52 AM UTC+1, fmatth...@gmail.com wrote:
>
> Sure, is there a working implementation of your proposal? I don't have a
> lot of free time so it will be slow, but I can take a look. If so, I might
> like to help work on the library features that come after your proposal.
>
> The list I made is a general sketch of some of the things I think might be
> immediatly useful. Many of these I already do manually using crude
> interfaces now. It will take some time to come up with a solid library
> design with a correctly chosen and designed features.
>
>
>
> On Saturday, January 11, 2014 11:39:50 PM UTC-5, Andrew Tomazos wrote:
>>
>> Could you please review N3815 (
>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3815.html) and
>> confirm that you can implement your enum_traits and enum_table class as a
>> pure library feature on top of the three provided type traits, and that the
>> solution would be as efficient as if the compiler did it for you?
>>
>> If you are unsure or think you have a feature you want that could not be
>> implemented on top of the N3815 type traits as an efficient pure library
>> feature, could you please point it out?
>>
>> Our current plan is to standardize N3815 in the Library Fundamentals TS
>> as a minmal complete interface that enables library / framework authors to
>> provide all this functionality that you want.
>>
>> From a review of your enum_traits and enum_table class I believe that
>> this is indeed the case - that both could all be built efficiently as a
>> pure library solution on top of the N3815.  Could you see if you agree.
>>
>> Thanks,
>> Andrew.
>>
>>
>>
>> On Saturday, January 11, 2014 7:47:48 AM UTC+1, fmatth...@gmail.comwrote:
>>>
>>> Enums are one of my favorite tools for efficently labeling collections,
>>> but we need to be able to query more information about them.
>>>
>>> I'd like to suggest some form of enum traits.
>>>
>>> template <typename E>
>>> struct enum_traits<E> {
>>>   static_assert(is_enum<E>::value, "Only valid for enums!");
>>>
>>>   typedef /* underlying type */ value_type;
>>>   static constexpr const value_type min = /* minimum value of enum */
>>>   static constexpr const value_type max = /* maximum value of enum */
>>>   static constexpr const value_type ubound = /* maximum value of enum+1.
>>> Not present (does not compile if queried) if max ==
>>> numeric_limits<value_type>::max(). (Note: this is the most useful value)*/
>>>
>>>   static constexpr const size_t count = /* Number of enum tags */
>>>   static constexpr const size_t distinct = /* Number of enum tags with
>>> distinct values */
>>>   static constexpr const bool is_contiguious = /* true if enum values
>>> are contiguous */
>>>   static constexpr const bool is_regular = is_contiguous && min ==
>>> value_type(0);
>>>   static constexpr const bool has_zero = /* true if zero is an enum
>>> value */
>>>   static constexpr const bool has_postive = /* true if at least one enum
>>> value is positive */
>>>   static constexpr const bool all_postive = /* true if all enum values
>>> are positive */
>>>   static constexpr const bool has_negative = /* true if at least one
>>> enum value is negative */
>>>   static constexpr const bool all_negative = /* true if all enum values
>>> are negative */
>>>
>>> //Utilities to enable foreach, compiler generated
>>>   class iterator : public std::bidirectional_iterator<E> {
>>>     public:
>>>       E operator*();
>>>       //iterator stuff, operator++ goes to next enum value in
>>> operator<() order.
>>>   };
>>>   class reverse_iterator;
>>>   struct range {
>>>
>>>     iterator begin();
>>>     iterator end();
>>>
>>>     reverse_iterator rbegin();
>>>     reverse_iterator rend();
>>>   };
>>>
>>>   range<E> loop();
>>> };
>>>
>>> //foreach loop over enum values
>>> for(auto e : enum_traits<E>::loop()) {
>>> };
>>>
>>> //Create tables keyed by enums, standard library component
>>> template <typename E, typename T, typename CMP = std::equal_to>
>>> class enum_table {
>>>   //static asserts if li.size() != enum_traits<E>::distinct;
>>>   constexpr enum_table(std::initializer_list<T> li);
>>>   constexpr enum_table(const enum_table&) = default;
>>>   constexpr enum_table(enum_table&&) = default;
>>>   constexpr enum_table& operator=(const enum_table&) = default;
>>>   constexpr enum_table& operator=(enum_table&&) = default;
>>>
>>>   constexpr const T& operator[E tag] const;
>>>   constexpr bool lookup(const T& value, E& tag) const;
>>>   constexpr bool lookup(T&& value, E& tag) const;
>>>   constexpr size_t size() const;
>>>
>>>   class iterator : std::bidirectional_iterator<std::pair<E, const T&>>
>>> {};
>>>   class reverse_iterator;
>>>
>>>   constexpr iterator begin();
>>>   constexpr iterator end();
>>>   constexpr reverse_iterator rbegin();
>>>   constexpr reverse_iterator rend();
>>>
>>>   constexpr iterator find(E tag);
>>>   template <typename Comparable>
>>>   constexpr iterator find(Comparable&& c); //lookup using CMP(const T&,
>>> C&&) or CMP(const T&, const C&) using perfect forwarding
>>>   constexpr iterator find(T&& value); //lookup using CMP()
>>> };
>>>
>>> template <typename E>
>>> using enum_strtable = enum_table<E, const char*, [](const char* l, const
>>> char* r){ return strcmp(l, r) == 0; }>;
>>>
>>>
>>> //Usage
>>> enum Color {
>>>   kRed,
>>>   kGreen,
>>>   kBlue
>>> };
>>>
>>> //Could be place in binary .rodata section.
>>> constexpr const enumstr_table<Color> color_tbl = { "Red", "Blue",
>>> "Green" };
>>>
>>> assert(!strcmp(color_tbl[kRed], "Red"));
>>> assert(color_tbl.find("Red") != color_tbl.end());
>>>
>>> I really want this for ubound, and loop(), and runtime string tables but
>>> while we're at it, there's a lot of cool stuff we could add.
>>> Rationale here:
>>>
>>> https://groups.google.com/forum/#!searchin/comp.lang.c$2B$2B.moderated/enum/comp.lang.c++.moderated/RpUiU9utY48/N-oUkAo5oIoJ
>>>
>>> Other extensions I'd love to see:
>>> * enum bitmasks as a real type, easy and expressive to declare, strict
>>> rules about logical operator comparisons. Only the tags in the enum can use
>>> binary logical operations with one another.
>>> * concepts in the enum declaration to enforce restrictions
>>> (is_contiguous, min == 0, etc..)
>>>
>>>
>>>

--

---
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_659_29162198.1389510072208
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>So, first yes, my co-author Christian has written a r=
eference implementation that contains a superset of the N3815 proposed thre=
e property queries. &nbsp;You will find the link on the bottom of N3815. &n=
bsp;This has been forked and extended by Remotion (linked previously in thi=
s thread).</div><div><br></div><div>But before you go diving into that and =
compiling custom implementation, the three traits are really simple to unde=
rstand and to mock up by hand with an ordinary compiler:</div><div><br></di=
v><div>First recall the three property queries are:</div><div><br></div><di=
v>&nbsp; &nbsp; <font face=3D"courier new, monospace">enumerator_list_size&=
lt;E&gt;</font> is the number of enumerators in the enumeration E</div><div=
>&nbsp; &nbsp; <font face=3D"courier new, monospace">enumerator_value&lt;E,=
I&gt;</font> is a value of type E that is the I'th enumerator in declared o=
rder.</div><div>&nbsp; &nbsp; <font face=3D"courier new, monospace">enumera=
tor_identifier&lt;E,I&gt;</font> is a string literal with the identifier of=
 the I'th enumerator in declared order.</div><div><br></div><div>So you can=
 mock them up for experimentation "by hand" without compiler changes as fol=
lows:</div><div><br></div><div>First declare but don't define the three N38=
15 primaries...</div><div><br></div><div><font face=3D"courier new, monospa=
ce">&nbsp; &nbsp; template&lt;typename E&gt; struct enumerator_list_size;</=
font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; templat=
e&lt;typename E, size_t I&gt; struct enumerator_value;</font></div><div><fo=
nt face=3D"courier new, monospace">&nbsp; &nbsp; template&lt;typename E, si=
ze_t I&gt; struct enumerator_identifier;</font></div><div><br></div><div>Th=
en for each enumeration type in your test program, for example...</div><div=
><br></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; enum fo=
o</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; {</f=
ont></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &=
nbsp; bar,</font></div><div><font face=3D"courier new, monospace">&nbsp; &n=
bsp; &nbsp; &nbsp; Baz,</font></div><div><font face=3D"courier new, monospa=
ce">&nbsp; &nbsp; &nbsp; &nbsp; Qux =3D 42,</font></div><div><font face=3D"=
courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; Quux =3D 42,</font></di=
v><div><font face=3D"courier new, monospace">&nbsp; &nbsp; };</font></div><=
div><br></div><div>...manually define a set of specializations by hand as f=
ollows...</div><div><br></div><div><font face=3D"courier new, monospace">&n=
bsp; &nbsp; template&lt;&gt; struct enumerator_list_size&lt;foo&gt; { stati=
c constexpr size_t value =3D 4; };</font></div><div><font face=3D"courier n=
ew, monospace"><br></font></div><div><font face=3D"courier new, monospace">=
&nbsp; &nbsp; template&lt;&gt; struct enumerator_value&lt;foo,0&gt; { stati=
c constexpr foo value =3D bar; };</font></div><div><font face=3D"courier ne=
w, monospace">&nbsp; &nbsp; template&lt;&gt; struct enumerator_value&lt;foo=
,1&gt; { static constexpr foo value =3D Baz; };</font></div><div><font face=
=3D"courier new, monospace">&nbsp; &nbsp; template&lt;&gt; struct enumerato=
r_value&lt;foo,2&gt; { static constexpr foo value =3D Qux; };</font></div><=
div><font face=3D"courier new, monospace">&nbsp; &nbsp; template&lt;&gt; st=
ruct enumerator_value&lt;foo,3&gt; { static constexpr foo value =3D Quux; }=
;</font></div><div><font face=3D"courier new, monospace"><br></font></div><=
div><font face=3D"courier new, monospace">&nbsp; &nbsp; template&lt;&gt; st=
ruct enumerator_identifier&lt;foo,0&gt; { static constexpr char value[4] =
=3D u8"bar"; };</font></div><div><font face=3D"courier new, monospace">&nbs=
p; &nbsp; template&lt;&gt; struct enumerator_identifier&lt;foo,1&gt; { stat=
ic constexpr char value[4] =3D u8"Baz"; };</font></div><div><font face=3D"c=
ourier new, monospace">&nbsp; &nbsp; template&lt;&gt; struct enumerator_ide=
ntifier&lt;foo,2&gt; { static constexpr char value[4] =3D u8"Qux"; };</font=
></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; template&lt=
;&gt; struct enumerator_identifier&lt;foo,3&gt; { static constexpr char val=
ue[5] =3D u8"Quux"; };</font></div><div><font face=3D"courier new, monospac=
e"><br></font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp=
; constexpr char enumerator_identifier&lt;foo,0&gt;::value[];</font></div><=
div><font face=3D"courier new, monospace">&nbsp; &nbsp; constexpr char enum=
erator_identifier&lt;foo,1&gt;::value[];</font></div><div><font face=3D"cou=
rier new, monospace">&nbsp; &nbsp; constexpr char enumerator_identifier&lt;=
foo,2&gt;::value[];</font></div><div><font face=3D"courier new, monospace">=
&nbsp; &nbsp; constexpr char enumerator_identifier&lt;foo,3&gt;::value[];</=
font></div><div><br></div><div>(The effect of N3815 is that these hand-writ=
ten specializations will be done automatically for you by the compiler when=
 you use them.)</div><div><br></div><div>Here is a complete self-contained =
compiling program with the above integrated together you can copy and paste=
 plus some tests:</div><div><br></div><div><font face=3D"courier new, monos=
pace">&nbsp; &nbsp; #include &lt;cassert&gt;</font></div><div><font face=3D=
"courier new, monospace">&nbsp; &nbsp; #include &lt;cstddef&gt;</font></div=
><div><font face=3D"courier new, monospace">&nbsp; &nbsp; #include &lt;stri=
ng.h&gt;</font></div><div><font face=3D"courier new, monospace"><br></font>=
</div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; // N3815 pri=
maries</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp;=
 template&lt;typename E&gt; struct enumerator_list_size;</font></div><div><=
font face=3D"courier new, monospace">&nbsp; &nbsp; template&lt;typename E, =
size_t I&gt; struct enumerator_value;</font></div><div><font face=3D"courie=
r new, monospace">&nbsp; &nbsp; template&lt;typename E, size_t I&gt; struct=
 enumerator_identifier;</font></div><div><font face=3D"courier new, monospa=
ce"><br></font></div><div><font face=3D"courier new, monospace">&nbsp; &nbs=
p; // your enumeration</font></div><div><font face=3D"courier new, monospac=
e">&nbsp; &nbsp; enum foo</font></div><div><font face=3D"courier new, monos=
pace">&nbsp; &nbsp; {</font></div><div><font face=3D"courier new, monospace=
">&nbsp; &nbsp; &nbsp; &nbsp; bar,</font></div><div><font face=3D"courier n=
ew, monospace">&nbsp; &nbsp; &nbsp; &nbsp; Baz,</font></div><div><font face=
=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; Qux =3D 42,</font><=
/div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp;=
 Quux =3D 42,</font></div><div><font face=3D"courier new, monospace">&nbsp;=
 &nbsp; };</font></div><div><font face=3D"courier new, monospace"><br></fon=
t></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; // define =
these specializations by hand:</font></div><div><font face=3D"courier new, =
monospace">&nbsp; &nbsp; template&lt;&gt; struct enumerator_list_size&lt;fo=
o&gt; { static constexpr size_t value =3D 4; };</font></div><div><font face=
=3D"courier new, monospace"><br></font></div><div><font face=3D"courier new=
, monospace">&nbsp; &nbsp; template&lt;&gt; struct enumerator_value&lt;foo,=
0&gt; { static constexpr foo value =3D bar; };</font></div><div><font face=
=3D"courier new, monospace">&nbsp; &nbsp; template&lt;&gt; struct enumerato=
r_value&lt;foo,1&gt; { static constexpr foo value =3D Baz; };</font></div><=
div><font face=3D"courier new, monospace">&nbsp; &nbsp; template&lt;&gt; st=
ruct enumerator_value&lt;foo,2&gt; { static constexpr foo value =3D Qux; };=
</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; templ=
ate&lt;&gt; struct enumerator_value&lt;foo,3&gt; { static constexpr foo val=
ue =3D Quux; };</font></div><div><font face=3D"courier new, monospace"><br>=
</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; templ=
ate&lt;&gt; struct enumerator_identifier&lt;foo,0&gt; { static constexpr ch=
ar value[4] =3D u8"bar"; };</font></div><div><font face=3D"courier new, mon=
ospace">&nbsp; &nbsp; template&lt;&gt; struct enumerator_identifier&lt;foo,=
1&gt; { static constexpr char value[4] =3D u8"Baz"; };</font></div><div><fo=
nt face=3D"courier new, monospace">&nbsp; &nbsp; template&lt;&gt; struct en=
umerator_identifier&lt;foo,2&gt; { static constexpr char value[4] =3D u8"Qu=
x"; };</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp;=
 template&lt;&gt; struct enumerator_identifier&lt;foo,3&gt; { static conste=
xpr char value[5] =3D u8"Quux"; };</font></div><div><font face=3D"courier n=
ew, monospace"><br></font></div><div><font face=3D"courier new, monospace">=
&nbsp; &nbsp; constexpr char enumerator_identifier&lt;foo,0&gt;::value[];</=
font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; constex=
pr char enumerator_identifier&lt;foo,1&gt;::value[];</font></div><div><font=
 face=3D"courier new, monospace">&nbsp; &nbsp; constexpr char enumerator_id=
entifier&lt;foo,2&gt;::value[];</font></div><div><font face=3D"courier new,=
 monospace">&nbsp; &nbsp; constexpr char enumerator_identifier&lt;foo,3&gt;=
::value[];</font></div><div><font face=3D"courier new, monospace"><br></fon=
t></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; // test th=
ey work:</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbs=
p; int main()</font></div><div><font face=3D"courier new, monospace">&nbsp;=
 &nbsp; {</font></div><div><font face=3D"courier new, monospace">&nbsp; &nb=
sp; &nbsp; &nbsp; static_assert(enumerator_list_size&lt;foo&gt;::value =3D=
=3D 4, "");</font></div><div><font face=3D"courier new, monospace"><br></fo=
nt></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &n=
bsp; assert(strcmp(enumerator_identifier&lt;foo,0&gt;::value, u8"bar") =3D=
=3D 0);</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp=
; &nbsp; &nbsp; assert(strcmp(enumerator_identifier&lt;foo,1&gt;::value, u8=
"Baz") =3D=3D 0);</font></div><div><font face=3D"courier new, monospace">&n=
bsp; &nbsp; &nbsp; &nbsp; assert(strcmp(enumerator_identifier&lt;foo,2&gt;:=
:value, u8"Qux") =3D=3D 0);</font></div><div><font face=3D"courier new, mon=
ospace">&nbsp; &nbsp; &nbsp; &nbsp; assert(strcmp(enumerator_identifier&lt;=
foo,3&gt;::value, u8"Quux") =3D=3D 0);</font></div><div><font face=3D"couri=
er new, monospace">&nbsp; &nbsp; &nbsp; &nbsp;</font></div><div><font face=
=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; static_assert(enume=
rator_value&lt;foo,0&gt;::value =3D=3D bar, "");</font></div><div><font fac=
e=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; static_assert(enum=
erator_value&lt;foo,1&gt;::value =3D=3D Baz, "");</font></div><div><font fa=
ce=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; static_assert(enu=
merator_value&lt;foo,2&gt;::value =3D=3D Qux, "");</font></div><div><font f=
ace=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; static_assert(en=
umerator_value&lt;foo,3&gt;::value =3D=3D Quux, "");</font></div><div><font=
 face=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp;</font></div><d=
iv><font face=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; conste=
xpr const char* str =3D enumerator_identifier&lt;foo,0&gt;::value;</font></=
div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; =
static_assert(str[0] =3D=3D 'b', "");</font></div><div><font face=3D"courie=
r new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; static_assert(str[1] =3D=3D '=
a', "");</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbs=
p; &nbsp; &nbsp; static_assert(str[2] =3D=3D 'r', "");</font></div><div><fo=
nt face=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; static_asser=
t(str[3] =3D=3D '\0', "");</font></div><div><font face=3D"courier new, mono=
space">&nbsp; &nbsp; }</font></div><div><br></div><div>Enjoy,</div><div>And=
rew.</div><div><br></div><br>On Sunday, January 12, 2014 6:16:52 AM UTC+1, =
fmatth...@gmail.com 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">Sure, is there a working implementation of your proposal? I do=
n't have a lot of free time so it will be slow, but I can take a look. If s=
o, I might like to help work on the library features that come after your p=
roposal.&nbsp;<div><br></div><div>The list I made is a general sketch of so=
me of the things I think might be immediatly useful. Many of these I alread=
y do manually using crude interfaces now. It will take some time to come up=
 with a solid library design with a correctly chosen and designed features.=
</div><div><br></div><div><br><br>On Saturday, January 11, 2014 11:39:50 PM=
 UTC-5, Andrew Tomazos wrote:<blockquote class=3D"gmail_quote" style=3D"mar=
gin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div d=
ir=3D"ltr">Could you please review N3815 (<a href=3D"http://www.open-std.or=
g/jtc1/sc22/wg21/docs/papers/2013/n3815.html" target=3D"_blank" onmousedown=
=3D"this.href=3D'http://www.google.com/url?q\75http%3A%2F%2Fwww.open-std.or=
g%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2013%2Fn3815.html\46sa\75D\46sntz\=
0751\46usg\75AFQjCNHwe7liqoidkU5rvKFSWklGuTd4gw';return true;" onclick=3D"t=
his.href=3D'http://www.google.com/url?q\75http%3A%2F%2Fwww.open-std.org%2Fj=
tc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2013%2Fn3815.html\46sa\75D\46sntz\0751\=
46usg\75AFQjCNHwe7liqoidkU5rvKFSWklGuTd4gw';return true;">http://www.open-s=
td.org/jtc1/<wbr>sc22/wg21/docs/papers/2013/<wbr>n3815.html</a>)&nbsp;and c=
onfirm that you can implement your enum_traits and enum_table class as a pu=
re library feature on top of the three provided type traits, and that the s=
olution would be as efficient as if the compiler did it for you?<div><br></=
div><div>If you are unsure or think you have a feature you want that could =
not be implemented on top of the N3815 type traits as an efficient pure lib=
rary feature, could you please point it out?</div><div><br></div><div>Our c=
urrent plan is to standardize N3815 in the Library Fundamentals TS as a min=
mal complete interface that enables library / framework authors to provide =
all this functionality that you want.</div><div><br></div><div>From a revie=
w of your enum_traits and enum_table class I believe that this is indeed th=
e case - that both could all be built efficiently as a pure library solutio=
n on top of the N3815. &nbsp;Could you see if you agree.<br><br>Thanks,</di=
v><div>Andrew.</div><div><br><br><br>On Saturday, January 11, 2014 7:47:48 =
AM UTC+1, <a>fmatth...@gmail.com</a> wrote:<blockquote class=3D"gmail_quote=
" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-le=
ft:1ex"><div dir=3D"ltr">Enums are one of my favorite tools for efficently =
labeling collections, but we need to be able to query more information abou=
t them.<div><br></div><div>I'd like to suggest some form of enum traits.&nb=
sp;</div><div><br></div><div>template &lt;typename E&gt;</div><div>struct e=
num_traits&lt;E&gt; {</div><div>&nbsp; static_assert(is_enum&lt;E&gt;::<wbr=
>value, "Only valid for enums!");</div><div>&nbsp;&nbsp;</div><div>&nbsp; t=
ypedef /* underlying type */ value_type;</div><div>&nbsp; static constexpr =
const value_type min =3D /* minimum value of enum */</div><div>&nbsp; stati=
c constexpr const value_type max =3D /* maximum value of enum */</div><div>=
&nbsp; static constexpr const value_type ubound =3D /* maximum value of enu=
m+1. Not present (does not compile if queried) if max =3D=3D numeric_limits=
&lt;value_type&gt;::<wbr>max(). (Note: this is the most useful value)*/</di=
v><div><br></div><div>&nbsp; static constexpr const size_t count =3D /* Num=
ber of enum tags */</div><div>&nbsp; static constexpr const size_t distinct=
 =3D /* Number of enum tags with distinct values */&nbsp;</div><div>&nbsp; =
static constexpr const bool is_contiguious =3D /* true if enum values are c=
ontiguous */</div><div>&nbsp; static constexpr const bool is_regular =3D is=
_contiguous &amp;&amp; min =3D=3D value_type(0);</div><div>&nbsp; static co=
nstexpr const bool has_zero =3D /* true if zero is an enum value */</div><d=
iv>&nbsp; static constexpr const bool has_postive =3D /* true if at least o=
ne enum value is positive */</div><div>&nbsp; static constexpr const bool a=
ll_postive =3D /* true if all enum values are positive */</div><div>&nbsp; =
static constexpr const bool has_negative =3D /* true if at least one enum v=
alue is negative */</div><div>&nbsp; static constexpr const bool all_negati=
ve =3D /* true if all enum values are negative */</div><div><br></div><div>=
//Utilities to enable foreach, compiler generated</div><div>&nbsp; class it=
erator : public std::bidirectional_iterator&lt;E&gt; {</div><div>&nbsp; &nb=
sp; public:</div><div>&nbsp; &nbsp; &nbsp; E operator*();</div><div>&nbsp; =
&nbsp; &nbsp; //iterator stuff, operator++ goes to next enum value in opera=
tor&lt;() order.</div><div>&nbsp; };</div><div>&nbsp; class reverse_iterato=
r;</div><div>&nbsp; struct range {</div><div><br></div><div>&nbsp; &nbsp; i=
terator begin();</div><div>&nbsp; &nbsp; iterator end();</div><div><br></di=
v><div>&nbsp; &nbsp; reverse_iterator rbegin();</div><div>&nbsp; &nbsp; rev=
erse_iterator rend();<br>&nbsp; };</div><div><br></div><div>&nbsp; range&lt=
;E&gt; loop();</div><div>};</div><div><br></div><div>//foreach loop over en=
um values</div><div>for(auto e : enum_traits&lt;E&gt;::loop()) {<br>};</div=
><div><br></div><div>//Create tables keyed by enums, standard library compo=
nent</div><div>template &lt;typename E, typename T, typename CMP =3D std::e=
qual_to&gt;</div><div>class enum_table {</div><div>&nbsp; //static asserts =
if li.size() !=3D enum_traits&lt;E&gt;::distinct;</div><div>&nbsp; constexp=
r enum_table(std::initializer_<wbr>list&lt;T&gt; li);</div><div>&nbsp; cons=
texpr enum_table(const enum_table&amp;) =3D default;</div><div>&nbsp; const=
expr enum_table(enum_table&amp;&amp;) =3D default;</div><div><div>&nbsp; co=
nstexpr enum_table&amp; operator=3D(const enum_table&amp;) =3D default;</di=
v><div>&nbsp; constexpr enum_table&amp; operator=3D(enum_table&amp;&amp;) =
=3D default;</div></div><div><br></div><div>&nbsp; constexpr const T&amp; o=
perator[E tag] const;</div><div>&nbsp; constexpr bool lookup(const T&amp; v=
alue, E&amp; tag) const;</div><div>&nbsp; constexpr bool lookup(T&amp;&amp;=
 value, E&amp; tag) const;</div><div>&nbsp; constexpr size_t size() const;<=
/div><div><br></div><div>&nbsp; class iterator : std::bidirectional_iterato=
r&lt;<wbr>std::pair&lt;E, const T&amp;&gt;&gt; {};</div><div>&nbsp; class r=
everse_iterator;</div><div>&nbsp;&nbsp;</div><div>&nbsp; constexpr iterator=
 begin();</div><div>&nbsp; constexpr iterator end();</div><div><div>&nbsp; =
constexpr reverse_iterator rbegin();</div><div>&nbsp; constexpr reverse_ite=
rator rend();</div><div><br></div><div>&nbsp; constexpr iterator find(E tag=
);</div><div>&nbsp; template &lt;typename Comparable&gt;</div><div>&nbsp; c=
onstexpr iterator find(Comparable&amp;&amp; c); //lookup using CMP(const T&=
amp;, C&amp;&amp;) or CMP(const T&amp;, const C&amp;) using perfect forward=
ing</div><div>&nbsp; constexpr iterator find(T&amp;&amp; value); //lookup u=
sing CMP()</div>};</div><div><br></div><div>template &lt;typename E&gt;</di=
v><div>using enum_strtable =3D enum_table&lt;E, const char*, [](const char*=
 l, const char* r){ return strcmp(l, r) =3D=3D 0; }&gt;;</div><div><br></di=
v><div><br></div><div>//Usage</div><div>enum Color {<br>&nbsp; kRed,</div><=
div>&nbsp; kGreen,</div><div>&nbsp; kBlue</div><div>};</div><div><br></div>=
<div>//Could be place in binary .rodata section.</div><div>constexpr const =
enumstr_table&lt;Color&gt; color_tbl =3D { "Red", "Blue", "Green" };</div><=
div><br></div><div>assert(!strcmp(color_tbl[kRed]<wbr>, "Red"));</div><div>=
assert(color_tbl.find("Red") !=3D color_tbl.end());</div><div><br></div><di=
v>I really want this for ubound, and loop(), and runtime string tables but =
while we're at it, there's a lot of cool stuff we could add.</div><div>Rati=
onale here:</div><div><a href=3D"https://groups.google.com/forum/#!searchin=
/comp.lang.c$2B$2B.moderated/enum/comp.lang.c++.moderated/RpUiU9utY48/N-oUk=
Ao5oIoJ" target=3D"_blank" onmousedown=3D"this.href=3D'https://groups.googl=
e.com/forum/#!searchin/comp.lang.c$2B$2B.moderated/enum/comp.lang.c++.moder=
ated/RpUiU9utY48/N-oUkAo5oIoJ';return true;" onclick=3D"this.href=3D'https:=
//groups.google.com/forum/#!searchin/comp.lang.c$2B$2B.moderated/enum/comp.=
lang.c++.moderated/RpUiU9utY48/N-oUkAo5oIoJ';return true;">https://groups.g=
oogle.com/<wbr>forum/#!searchin/comp.lang.c$<wbr>2B$2B.moderated/enum/comp.=
<wbr>lang.c++.moderated/<wbr>RpUiU9utY48/N-oUkAo5oIoJ</a><br></div><div><br=
></div><div>Other extensions I'd love to see:</div><div>* enum bitmasks as =
a real type, easy and expressive to declare, strict rules about logical ope=
rator comparisons. Only the tags in the enum can use binary logical operati=
ons with one another.</div><div>* concepts in the enum declaration to enfor=
ce restrictions (is_contiguous, min =3D=3D 0, etc..)</div><div><br></div><d=
iv><br></div></div></blockquote></div></div></blockquote></div></div></bloc=
kquote></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_659_29162198.1389510072208--

.


Author: inkwizytoryankes@gmail.com
Date: Sun, 12 Jan 2014 07:41:30 -0800 (PST)
Raw View
------=_Part_2433_32256789.1389541290361
Content-Type: text/plain; charset=ISO-8859-1

Would be possible to create similar functionality for class? If this enum
approach is possible to implement by every compiler, creating version for
class should not be impossible.
This would be more complex because class have private, static, unions,
fields, base class, sub class and functions, but if we can made interface
for one thing then creating for rest wouldnt be harder.

On Sunday, January 12, 2014 8:01:12 AM UTC+1, Andrew Tomazos wrote:
>
> So, first yes, my co-author Christian has written a reference
> implementation that contains a superset of the N3815 proposed three
> property queries.  You will find the link on the bottom of N3815.  This has
> been forked and extended by Remotion (linked previously in this thread).
>
> But before you go diving into that and compiling custom implementation,
> the three traits are really simple to understand and to mock up by hand
> with an ordinary compiler:
>
> First recall the three property queries are:
>
>     enumerator_list_size<E> is the number of enumerators in the
> enumeration E
>     enumerator_value<E,I> is a value of type E that is the I'th
> enumerator in declared order.
>     enumerator_identifier<E,I> is a string literal with the identifier of
> the I'th enumerator in declared order.
>
> So you can mock them up for experimentation "by hand" without compiler
> changes as follows:
>
> First declare but don't define the three N3815 primaries...
>
>     template<typename E> struct enumerator_list_size;
>     template<typename E, size_t I> struct enumerator_value;
>     template<typename E, size_t I> struct enumerator_identifier;
>
> Then for each enumeration type in your test program, for example...
>
>     enum foo
>     {
>         bar,
>         Baz,
>         Qux = 42,
>         Quux = 42,
>     };
>
> ...manually define a set of specializations by hand as follows...
>
>     template<> struct enumerator_list_size<foo> { static constexpr size_t
> value = 4; };
>
>     template<> struct enumerator_value<foo,0> { static constexpr foo value
> = bar; };
>     template<> struct enumerator_value<foo,1> { static constexpr foo value
> = Baz; };
>     template<> struct enumerator_value<foo,2> { static constexpr foo value
> = Qux; };
>     template<> struct enumerator_value<foo,3> { static constexpr foo value
> = Quux; };
>
>     template<> struct enumerator_identifier<foo,0> { static constexpr char
> value[4] = u8"bar"; };
>     template<> struct enumerator_identifier<foo,1> { static constexpr char
> value[4] = u8"Baz"; };
>     template<> struct enumerator_identifier<foo,2> { static constexpr char
> value[4] = u8"Qux"; };
>     template<> struct enumerator_identifier<foo,3> { static constexpr char
> value[5] = u8"Quux"; };
>
>     constexpr char enumerator_identifier<foo,0>::value[];
>     constexpr char enumerator_identifier<foo,1>::value[];
>     constexpr char enumerator_identifier<foo,2>::value[];
>     constexpr char enumerator_identifier<foo,3>::value[];
>
> (The effect of N3815 is that these hand-written specializations will be
> done automatically for you by the compiler when you use them.)
>
> Here is a complete self-contained compiling program with the above
> integrated together you can copy and paste plus some tests:
>
>     #include <cassert>
>     #include <cstddef>
>     #include <string.h>
>
>     // N3815 primaries
>     template<typename E> struct enumerator_list_size;
>     template<typename E, size_t I> struct enumerator_value;
>     template<typename E, size_t I> struct enumerator_identifier;
>
>     // your enumeration
>     enum foo
>     {
>         bar,
>         Baz,
>         Qux = 42,
>         Quux = 42,
>     };
>
>     // define these specializations by hand:
>     template<> struct enumerator_list_size<foo> { static constexpr size_t
> value = 4; };
>
>     template<> struct enumerator_value<foo,0> { static constexpr foo value
> = bar; };
>     template<> struct enumerator_value<foo,1> { static constexpr foo value
> = Baz; };
>     template<> struct enumerator_value<foo,2> { static constexpr foo value
> = Qux; };
>     template<> struct enumerator_value<foo,3> { static constexpr foo value
> = Quux; };
>
>     template<> struct enumerator_identifier<foo,0> { static constexpr char
> value[4] = u8"bar"; };
>     template<> struct enumerator_identifier<foo,1> { static constexpr char
> value[4] = u8"Baz"; };
>     template<> struct enumerator_identifier<foo,2> { static constexpr char
> value[4] = u8"Qux"; };
>     template<> struct enumerator_identifier<foo,3> { static constexpr char
> value[5] = u8"Quux"; };
>
>     constexpr char enumerator_identifier<foo,0>::value[];
>     constexpr char enumerator_identifier<foo,1>::value[];
>     constexpr char enumerator_identifier<foo,2>::value[];
>     constexpr char enumerator_identifier<foo,3>::value[];
>
>     // test they work:
>     int main()
>     {
>         static_assert(enumerator_list_size<foo>::value == 4, "");
>
>         assert(strcmp(enumerator_identifier<foo,0>::value, u8"bar") == 0);
>         assert(strcmp(enumerator_identifier<foo,1>::value, u8"Baz") == 0);
>         assert(strcmp(enumerator_identifier<foo,2>::value, u8"Qux") == 0);
>         assert(strcmp(enumerator_identifier<foo,3>::value, u8"Quux") == 0);
>
>         static_assert(enumerator_value<foo,0>::value == bar, "");
>         static_assert(enumerator_value<foo,1>::value == Baz, "");
>         static_assert(enumerator_value<foo,2>::value == Qux, "");
>         static_assert(enumerator_value<foo,3>::value == Quux, "");
>
>         constexpr const char* str = enumerator_identifier<foo,0>::value;
>         static_assert(str[0] == 'b', "");
>         static_assert(str[1] == 'a', "");
>         static_assert(str[2] == 'r', "");
>         static_assert(str[3] == '\0', "");
>     }
>
> Enjoy,
> Andrew.
>
>
> On Sunday, January 12, 2014 6:16:52 AM UTC+1, fmatth...@gmail.com wrote:
>>
>> Sure, is there a working implementation of your proposal? I don't have a
>> lot of free time so it will be slow, but I can take a look. If so, I might
>> like to help work on the library features that come after your proposal.
>>
>> The list I made is a general sketch of some of the things I think might
>> be immediatly useful. Many of these I already do manually using crude
>> interfaces now. It will take some time to come up with a solid library
>> design with a correctly chosen and designed features.
>>
>>
>>
>> On Saturday, January 11, 2014 11:39:50 PM UTC-5, Andrew Tomazos wrote:
>>>
>>> Could you please review N3815 (
>>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3815.html) and
>>> confirm that you can implement your enum_traits and enum_table class as a
>>> pure library feature on top of the three provided type traits, and that the
>>> solution would be as efficient as if the compiler did it for you?
>>>
>>> If you are unsure or think you have a feature you want that could not be
>>> implemented on top of the N3815 type traits as an efficient pure library
>>> feature, could you please point it out?
>>>
>>> Our current plan is to standardize N3815 in the Library Fundamentals TS
>>> as a minmal complete interface that enables library / framework authors to
>>> provide all this functionality that you want.
>>>
>>> From a review of your enum_traits and enum_table class I believe that
>>> this is indeed the case - that both could all be built efficiently as a
>>> pure library solution on top of the N3815.  Could you see if you agree.
>>>
>>> Thanks,
>>> Andrew.
>>>
>>>
>>>
>>> On Saturday, January 11, 2014 7:47:48 AM UTC+1, fmatth...@gmail.comwrote:
>>>>
>>>> Enums are one of my favorite tools for efficently labeling collections,
>>>> but we need to be able to query more information about them.
>>>>
>>>> I'd like to suggest some form of enum traits.
>>>>
>>>> template <typename E>
>>>> struct enum_traits<E> {
>>>>   static_assert(is_enum<E>::value, "Only valid for enums!");
>>>>
>>>>   typedef /* underlying type */ value_type;
>>>>   static constexpr const value_type min = /* minimum value of enum */
>>>>   static constexpr const value_type max = /* maximum value of enum */
>>>>   static constexpr const value_type ubound = /* maximum value of
>>>> enum+1. Not present (does not compile if queried) if max ==
>>>> numeric_limits<value_type>::max(). (Note: this is the most useful value)*/
>>>>
>>>>   static constexpr const size_t count = /* Number of enum tags */
>>>>   static constexpr const size_t distinct = /* Number of enum tags with
>>>> distinct values */
>>>>   static constexpr const bool is_contiguious = /* true if enum values
>>>> are contiguous */
>>>>   static constexpr const bool is_regular = is_contiguous && min ==
>>>> value_type(0);
>>>>   static constexpr const bool has_zero = /* true if zero is an enum
>>>> value */
>>>>   static constexpr const bool has_postive = /* true if at least one
>>>> enum value is positive */
>>>>   static constexpr const bool all_postive = /* true if all enum values
>>>> are positive */
>>>>   static constexpr const bool has_negative = /* true if at least one
>>>> enum value is negative */
>>>>   static constexpr const bool all_negative = /* true if all enum values
>>>> are negative */
>>>>
>>>> //Utilities to enable foreach, compiler generated
>>>>   class iterator : public std::bidirectional_iterator<E> {
>>>>     public:
>>>>       E operator*();
>>>>       //iterator stuff, operator++ goes to next enum value in
>>>> operator<() order.
>>>>   };
>>>>   class reverse_iterator;
>>>>   struct range {
>>>>
>>>>     iterator begin();
>>>>     iterator end();
>>>>
>>>>     reverse_iterator rbegin();
>>>>     reverse_iterator rend();
>>>>   };
>>>>
>>>>   range<E> loop();
>>>> };
>>>>
>>>> //foreach loop over enum values
>>>> for(auto e : enum_traits<E>::loop()) {
>>>> };
>>>>
>>>> //Create tables keyed by enums, standard library component
>>>> template <typename E, typename T, typename CMP = std::equal_to>
>>>> class enum_table {
>>>>   //static asserts if li.size() != enum_traits<E>::distinct;
>>>>   constexpr enum_table(std::initializer_list<T> li);
>>>>   constexpr enum_table(const enum_table&) = default;
>>>>   constexpr enum_table(enum_table&&) = default;
>>>>   constexpr enum_table& operator=(const enum_table&) = default;
>>>>   constexpr enum_table& operator=(enum_table&&) = default;
>>>>
>>>>   constexpr const T& operator[E tag] const;
>>>>   constexpr bool lookup(const T& value, E& tag) const;
>>>>   constexpr bool lookup(T&& value, E& tag) const;
>>>>   constexpr size_t size() const;
>>>>
>>>>   class iterator : std::bidirectional_iterator<std::pair<E, const T&>>
>>>> {};
>>>>   class reverse_iterator;
>>>>
>>>>   constexpr iterator begin();
>>>>   constexpr iterator end();
>>>>   constexpr reverse_iterator rbegin();
>>>>   constexpr reverse_iterator rend();
>>>>
>>>>   constexpr iterator find(E tag);
>>>>   template <typename Comparable>
>>>>   constexpr iterator find(Comparable&& c); //lookup using CMP(const T&,
>>>> C&&) or CMP(const T&, const C&) using perfect forwarding
>>>>   constexpr iterator find(T&& value); //lookup using CMP()
>>>> };
>>>>
>>>> template <typename E>
>>>> using enum_strtable = enum_table<E, const char*, [](const char* l,
>>>> const char* r){ return strcmp(l, r) == 0; }>;
>>>>
>>>>
>>>> //Usage
>>>> enum Color {
>>>>   kRed,
>>>>   kGreen,
>>>>   kBlue
>>>> };
>>>>
>>>> //Could be place in binary .rodata section.
>>>> constexpr const enumstr_table<Color> color_tbl = { "Red", "Blue",
>>>> "Green" };
>>>>
>>>> assert(!strcmp(color_tbl[kRed], "Red"));
>>>> assert(color_tbl.find("Red") != color_tbl.end());
>>>>
>>>> I really want this for ubound, and loop(), and runtime string tables
>>>> but while we're at it, there's a lot of cool stuff we could add.
>>>> Rationale here:
>>>>
>>>> https://groups.google.com/forum/#!searchin/comp.lang.c$2B$2B.moderated/enum/comp.lang.c++.moderated/RpUiU9utY48/N-oUkAo5oIoJ
>>>>
>>>> Other extensions I'd love to see:
>>>> * enum bitmasks as a real type, easy and expressive to declare, strict
>>>> rules about logical operator comparisons. Only the tags in the enum can use
>>>> binary logical operations with one another.
>>>> * concepts in the enum declaration to enforce restrictions
>>>> (is_contiguous, min == 0, etc..)
>>>>
>>>>
>>>>

--

---
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_2433_32256789.1389541290361
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Would be possible to create similar functionality for clas=
s? If this enum approach is possible to implement by every compiler, creati=
ng version for class should not be impossible.<br>This would be more comple=
x because class have private, static, unions, fields, base class, sub class=
 and functions, but if we can made interface for one thing then creating fo=
r rest wouldnt be harder.<br><br>On Sunday, January 12, 2014 8:01:12 AM UTC=
+1, Andrew Tomazos 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>So, first yes, my co-author Christian has written a refere=
nce implementation that contains a superset of the N3815 proposed three pro=
perty queries. &nbsp;You will find the link on the bottom of N3815. &nbsp;T=
his has been forked and extended by Remotion (linked previously in this thr=
ead).</div><div><br></div><div>But before you go diving into that and compi=
ling custom implementation, the three traits are really simple to understan=
d and to mock up by hand with an ordinary compiler:</div><div><br></div><di=
v>First recall the three property queries are:</div><div><br></div><div>&nb=
sp; &nbsp; <font face=3D"courier new, monospace">enumerator_list_size&lt;E&=
gt;</font> is the number of enumerators in the enumeration E</div><div>&nbs=
p; &nbsp; <font face=3D"courier new, monospace">enumerator_value&lt;E,I&gt;=
</font> is a value of type E that is the I'th enumerator in declared order.=
</div><div>&nbsp; &nbsp; <font face=3D"courier new, monospace">enumerator_i=
dentifier&lt;E,I&gt;</font> is a string literal with the identifier of the =
I'th enumerator in declared order.</div><div><br></div><div>So you can mock=
 them up for experimentation "by hand" without compiler changes as follows:=
</div><div><br></div><div>First declare but don't define the three N3815 pr=
imaries...</div><div><br></div><div><font face=3D"courier new, monospace">&=
nbsp; &nbsp; template&lt;typename E&gt; struct enumerator_list_size;</font>=
</div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; template&lt;=
typename E, size_t I&gt; struct enumerator_value;</font></div><div><font fa=
ce=3D"courier new, monospace">&nbsp; &nbsp; template&lt;typename E, size_t =
I&gt; struct enumerator_identifier;</font></div><div><br></div><div>Then fo=
r each enumeration type in your test program, for example...</div><div><br>=
</div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; enum foo</fo=
nt></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; {</font><=
/div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp;=
 bar,</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; =
&nbsp; &nbsp; Baz,</font></div><div><font face=3D"courier new, monospace">&=
nbsp; &nbsp; &nbsp; &nbsp; Qux =3D 42,</font></div><div><font face=3D"couri=
er new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; Quux =3D 42,</font></div><di=
v><font face=3D"courier new, monospace">&nbsp; &nbsp; };</font></div><div><=
br></div><div>...manually define a set of specializations by hand as follow=
s...</div><div><br></div><div><font face=3D"courier new, monospace">&nbsp; =
&nbsp; template&lt;&gt; struct enumerator_list_size&lt;foo&gt; { static con=
stexpr size_t value =3D 4; };</font></div><div><font face=3D"courier new, m=
onospace"><br></font></div><div><font face=3D"courier new, monospace">&nbsp=
; &nbsp; template&lt;&gt; struct enumerator_value&lt;foo,0&gt; { static con=
stexpr foo value =3D bar; };</font></div><div><font face=3D"courier new, mo=
nospace">&nbsp; &nbsp; template&lt;&gt; struct enumerator_value&lt;foo,1&gt=
; { static constexpr foo value =3D Baz; };</font></div><div><font face=3D"c=
ourier new, monospace">&nbsp; &nbsp; template&lt;&gt; struct enumerator_val=
ue&lt;foo,2&gt; { static constexpr foo value =3D Qux; };</font></div><div><=
font face=3D"courier new, monospace">&nbsp; &nbsp; template&lt;&gt; struct =
enumerator_value&lt;foo,3&gt; { static constexpr foo value =3D Quux; };</fo=
nt></div><div><font face=3D"courier new, monospace"><br></font></div><div><=
font face=3D"courier new, monospace">&nbsp; &nbsp; template&lt;&gt; struct =
enumerator_identifier&lt;foo,0&gt; { static constexpr char value[4] =3D u8"=
bar"; };</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbs=
p; template&lt;&gt; struct enumerator_identifier&lt;foo,1&gt; { static cons=
texpr char value[4] =3D u8"Baz"; };</font></div><div><font face=3D"courier =
new, monospace">&nbsp; &nbsp; template&lt;&gt; struct enumerator_identifier=
&lt;foo,2&gt; { static constexpr char value[4] =3D u8"Qux"; };</font></div>=
<div><font face=3D"courier new, monospace">&nbsp; &nbsp; template&lt;&gt; s=
truct enumerator_identifier&lt;foo,3&gt; { static constexpr char value[5] =
=3D u8"Quux"; };</font></div><div><font face=3D"courier new, monospace"><br=
></font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; cons=
texpr char enumerator_identifier&lt;foo,0&gt;::<wbr>value[];</font></div><d=
iv><font face=3D"courier new, monospace">&nbsp; &nbsp; constexpr char enume=
rator_identifier&lt;foo,1&gt;::<wbr>value[];</font></div><div><font face=3D=
"courier new, monospace">&nbsp; &nbsp; constexpr char enumerator_identifier=
&lt;foo,2&gt;::<wbr>value[];</font></div><div><font face=3D"courier new, mo=
nospace">&nbsp; &nbsp; constexpr char enumerator_identifier&lt;foo,3&gt;::<=
wbr>value[];</font></div><div><br></div><div>(The effect of N3815 is that t=
hese hand-written specializations will be done automatically for you by the=
 compiler when you use them.)</div><div><br></div><div>Here is a complete s=
elf-contained compiling program with the above integrated together you can =
copy and paste plus some tests:</div><div><br></div><div><font face=3D"cour=
ier new, monospace">&nbsp; &nbsp; #include &lt;cassert&gt;</font></div><div=
><font face=3D"courier new, monospace">&nbsp; &nbsp; #include &lt;cstddef&g=
t;</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; #in=
clude &lt;string.h&gt;</font></div><div><font face=3D"courier new, monospac=
e"><br></font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp=
; // N3815 primaries</font></div><div><font face=3D"courier new, monospace"=
>&nbsp; &nbsp; template&lt;typename E&gt; struct enumerator_list_size;</fon=
t></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; template&l=
t;typename E, size_t I&gt; struct enumerator_value;</font></div><div><font =
face=3D"courier new, monospace">&nbsp; &nbsp; template&lt;typename E, size_=
t I&gt; struct enumerator_identifier;</font></div><div><font face=3D"courie=
r new, monospace"><br></font></div><div><font face=3D"courier new, monospac=
e">&nbsp; &nbsp; // your enumeration</font></div><div><font face=3D"courier=
 new, monospace">&nbsp; &nbsp; enum foo</font></div><div><font face=3D"cour=
ier new, monospace">&nbsp; &nbsp; {</font></div><div><font face=3D"courier =
new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; bar,</font></div><div><font fac=
e=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; Baz,</font></div><=
div><font face=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; Qux =
=3D 42,</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp=
; &nbsp; &nbsp; Quux =3D 42,</font></div><div><font face=3D"courier new, mo=
nospace">&nbsp; &nbsp; };</font></div><div><font face=3D"courier new, monos=
pace"><br></font></div><div><font face=3D"courier new, monospace">&nbsp; &n=
bsp; // define these specializations by hand:</font></div><div><font face=
=3D"courier new, monospace">&nbsp; &nbsp; template&lt;&gt; struct enumerato=
r_list_size&lt;foo&gt; { static constexpr size_t value =3D 4; };</font></di=
v><div><font face=3D"courier new, monospace"><br></font></div><div><font fa=
ce=3D"courier new, monospace">&nbsp; &nbsp; template&lt;&gt; struct enumera=
tor_value&lt;foo,0&gt; { static constexpr foo value =3D bar; };</font></div=
><div><font face=3D"courier new, monospace">&nbsp; &nbsp; template&lt;&gt; =
struct enumerator_value&lt;foo,1&gt; { static constexpr foo value =3D Baz; =
};</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; tem=
plate&lt;&gt; struct enumerator_value&lt;foo,2&gt; { static constexpr foo v=
alue =3D Qux; };</font></div><div><font face=3D"courier new, monospace">&nb=
sp; &nbsp; template&lt;&gt; struct enumerator_value&lt;foo,3&gt; { static c=
onstexpr foo value =3D Quux; };</font></div><div><font face=3D"courier new,=
 monospace"><br></font></div><div><font face=3D"courier new, monospace">&nb=
sp; &nbsp; template&lt;&gt; struct enumerator_identifier&lt;foo,0&gt; { sta=
tic constexpr char value[4] =3D u8"bar"; };</font></div><div><font face=3D"=
courier new, monospace">&nbsp; &nbsp; template&lt;&gt; struct enumerator_id=
entifier&lt;foo,1&gt; { static constexpr char value[4] =3D u8"Baz"; };</fon=
t></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; template&l=
t;&gt; struct enumerator_identifier&lt;foo,2&gt; { static constexpr char va=
lue[4] =3D u8"Qux"; };</font></div><div><font face=3D"courier new, monospac=
e">&nbsp; &nbsp; template&lt;&gt; struct enumerator_identifier&lt;foo,3&gt;=
 { static constexpr char value[5] =3D u8"Quux"; };</font></div><div><font f=
ace=3D"courier new, monospace"><br></font></div><div><font face=3D"courier =
new, monospace">&nbsp; &nbsp; constexpr char enumerator_identifier&lt;foo,0=
&gt;::<wbr>value[];</font></div><div><font face=3D"courier new, monospace">=
&nbsp; &nbsp; constexpr char enumerator_identifier&lt;foo,1&gt;::<wbr>value=
[];</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; co=
nstexpr char enumerator_identifier&lt;foo,2&gt;::<wbr>value[];</font></div>=
<div><font face=3D"courier new, monospace">&nbsp; &nbsp; constexpr char enu=
merator_identifier&lt;foo,3&gt;::<wbr>value[];</font></div><div><font face=
=3D"courier new, monospace"><br></font></div><div><font face=3D"courier new=
, monospace">&nbsp; &nbsp; // test they work:</font></div><div><font face=
=3D"courier new, monospace">&nbsp; &nbsp; int main()</font></div><div><font=
 face=3D"courier new, monospace">&nbsp; &nbsp; {</font></div><div><font fac=
e=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; static_assert(enum=
erator_list_<wbr>size&lt;foo&gt;::value =3D=3D 4, "");</font></div><div><fo=
nt face=3D"courier new, monospace"><br></font></div><div><font face=3D"cour=
ier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; assert(strcmp(enumerator_<w=
br>identifier&lt;foo,0&gt;::value, u8"bar") =3D=3D 0);</font></div><div><fo=
nt face=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; assert(strcm=
p(enumerator_<wbr>identifier&lt;foo,1&gt;::value, u8"Baz") =3D=3D 0);</font=
></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbs=
p; assert(strcmp(enumerator_<wbr>identifier&lt;foo,2&gt;::value, u8"Qux") =
=3D=3D 0);</font></div><div><font face=3D"courier new, monospace">&nbsp; &n=
bsp; &nbsp; &nbsp; assert(strcmp(enumerator_<wbr>identifier&lt;foo,3&gt;::v=
alue, u8"Quux") =3D=3D 0);</font></div><div><font face=3D"courier new, mono=
space">&nbsp; &nbsp; &nbsp; &nbsp;</font></div><div><font face=3D"courier n=
ew, monospace">&nbsp; &nbsp; &nbsp; &nbsp; static_assert(enumerator_<wbr>va=
lue&lt;foo,0&gt;::value =3D=3D bar, "");</font></div><div><font face=3D"cou=
rier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; static_assert(enumerator_<=
wbr>value&lt;foo,1&gt;::value =3D=3D Baz, "");</font></div><div><font face=
=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; static_assert(enume=
rator_<wbr>value&lt;foo,2&gt;::value =3D=3D Qux, "");</font></div><div><fon=
t face=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; static_assert=
(enumerator_<wbr>value&lt;foo,3&gt;::value =3D=3D Quux, "");</font></div><d=
iv><font face=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp;</font>=
</div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp=
; constexpr const char* str =3D enumerator_identifier&lt;foo,0&gt;::<wbr>va=
lue;</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; &=
nbsp; &nbsp; static_assert(str[0] =3D=3D 'b', "");</font></div><div><font f=
ace=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; static_assert(st=
r[1] =3D=3D 'a', "");</font></div><div><font face=3D"courier new, monospace=
">&nbsp; &nbsp; &nbsp; &nbsp; static_assert(str[2] =3D=3D 'r', "");</font><=
/div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp;=
 static_assert(str[3] =3D=3D '\0', "");</font></div><div><font face=3D"cour=
ier new, monospace">&nbsp; &nbsp; }</font></div><div><br></div><div>Enjoy,<=
/div><div>Andrew.</div><div><br></div><br>On Sunday, January 12, 2014 6:16:=
52 AM UTC+1, <a>fmatth...@gmail.com</a> wrote:<blockquote class=3D"gmail_qu=
ote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding=
-left:1ex"><div dir=3D"ltr">Sure, is there a working implementation of your=
 proposal? I don't have a lot of free time so it will be slow, but I can ta=
ke a look. If so, I might like to help work on the library features that co=
me after your proposal.&nbsp;<div><br></div><div>The list I made is a gener=
al sketch of some of the things I think might be immediatly useful. Many of=
 these I already do manually using crude interfaces now. It will take some =
time to come up with a solid library design with a correctly chosen and des=
igned features.</div><div><br></div><div><br><br>On Saturday, January 11, 2=
014 11:39:50 PM UTC-5, Andrew Tomazos wrote:<blockquote class=3D"gmail_quot=
e" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-l=
eft:1ex"><div dir=3D"ltr">Could you please review N3815 (<a href=3D"http://=
www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3815.html" target=3D"_bla=
nk" onmousedown=3D"this.href=3D'http://www.google.com/url?q\75http%3A%2F%2F=
www.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2013%2Fn3815.html\4=
6sa\75D\46sntz\0751\46usg\75AFQjCNHwe7liqoidkU5rvKFSWklGuTd4gw';return true=
;" onclick=3D"this.href=3D'http://www.google.com/url?q\75http%3A%2F%2Fwww.o=
pen-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2013%2Fn3815.html\46sa\7=
5D\46sntz\0751\46usg\75AFQjCNHwe7liqoidkU5rvKFSWklGuTd4gw';return true;">ht=
tp://www.open-std.org/jtc1/<wbr>sc22/wg21/docs/papers/2013/<wbr>n3815.html<=
/a>)&nbsp;and confirm that you can implement your enum_traits and enum_tabl=
e class as a pure library feature on top of the three provided type traits,=
 and that the solution would be as efficient as if the compiler did it for =
you?<div><br></div><div>If you are unsure or think you have a feature you w=
ant that could not be implemented on top of the N3815 type traits as an eff=
icient pure library feature, could you please point it out?</div><div><br><=
/div><div>Our current plan is to standardize N3815 in the Library Fundament=
als TS as a minmal complete interface that enables library / framework auth=
ors to provide all this functionality that you want.</div><div><br></div><d=
iv>From a review of your enum_traits and enum_table class I believe that th=
is is indeed the case - that both could all be built efficiently as a pure =
library solution on top of the N3815. &nbsp;Could you see if you agree.<br>=
<br>Thanks,</div><div>Andrew.</div><div><br><br><br>On Saturday, January 11=
, 2014 7:47:48 AM UTC+1, <a>fmatth...@gmail.com</a> wrote:<blockquote class=
=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr">Enums are one of my favorite tools =
for efficently labeling collections, but we need to be able to query more i=
nformation about them.<div><br></div><div>I'd like to suggest some form of =
enum traits.&nbsp;</div><div><br></div><div>template &lt;typename E&gt;</di=
v><div>struct enum_traits&lt;E&gt; {</div><div>&nbsp; static_assert(is_enum=
&lt;E&gt;::<wbr>value, "Only valid for enums!");</div><div>&nbsp;&nbsp;</di=
v><div>&nbsp; typedef /* underlying type */ value_type;</div><div>&nbsp; st=
atic constexpr const value_type min =3D /* minimum value of enum */</div><d=
iv>&nbsp; static constexpr const value_type max =3D /* maximum value of enu=
m */</div><div>&nbsp; static constexpr const value_type ubound =3D /* maxim=
um value of enum+1. Not present (does not compile if queried) if max =3D=3D=
 numeric_limits&lt;value_type&gt;::<wbr>max(). (Note: this is the most usef=
ul value)*/</div><div><br></div><div>&nbsp; static constexpr const size_t c=
ount =3D /* Number of enum tags */</div><div>&nbsp; static constexpr const =
size_t distinct =3D /* Number of enum tags with distinct values */&nbsp;</d=
iv><div>&nbsp; static constexpr const bool is_contiguious =3D /* true if en=
um values are contiguous */</div><div>&nbsp; static constexpr const bool is=
_regular =3D is_contiguous &amp;&amp; min =3D=3D value_type(0);</div><div>&=
nbsp; static constexpr const bool has_zero =3D /* true if zero is an enum v=
alue */</div><div>&nbsp; static constexpr const bool has_postive =3D /* tru=
e if at least one enum value is positive */</div><div>&nbsp; static constex=
pr const bool all_postive =3D /* true if all enum values are positive */</d=
iv><div>&nbsp; static constexpr const bool has_negative =3D /* true if at l=
east one enum value is negative */</div><div>&nbsp; static constexpr const =
bool all_negative =3D /* true if all enum values are negative */</div><div>=
<br></div><div>//Utilities to enable foreach, compiler generated</div><div>=
&nbsp; class iterator : public std::bidirectional_iterator&lt;E&gt; {</div>=
<div>&nbsp; &nbsp; public:</div><div>&nbsp; &nbsp; &nbsp; E operator*();</d=
iv><div>&nbsp; &nbsp; &nbsp; //iterator stuff, operator++ goes to next enum=
 value in operator&lt;() order.</div><div>&nbsp; };</div><div>&nbsp; class =
reverse_iterator;</div><div>&nbsp; struct range {</div><div><br></div><div>=
&nbsp; &nbsp; iterator begin();</div><div>&nbsp; &nbsp; iterator end();</di=
v><div><br></div><div>&nbsp; &nbsp; reverse_iterator rbegin();</div><div>&n=
bsp; &nbsp; reverse_iterator rend();<br>&nbsp; };</div><div><br></div><div>=
&nbsp; range&lt;E&gt; loop();</div><div>};</div><div><br></div><div>//forea=
ch loop over enum values</div><div>for(auto e : enum_traits&lt;E&gt;::loop(=
)) {<br>};</div><div><br></div><div>//Create tables keyed by enums, standar=
d library component</div><div>template &lt;typename E, typename T, typename=
 CMP =3D std::equal_to&gt;</div><div>class enum_table {</div><div>&nbsp; //=
static asserts if li.size() !=3D enum_traits&lt;E&gt;::distinct;</div><div>=
&nbsp; constexpr enum_table(std::initializer_<wbr>list&lt;T&gt; li);</div><=
div>&nbsp; constexpr enum_table(const enum_table&amp;) =3D default;</div><d=
iv>&nbsp; constexpr enum_table(enum_table&amp;&amp;) =3D default;</div><div=
><div>&nbsp; constexpr enum_table&amp; operator=3D(const enum_table&amp;) =
=3D default;</div><div>&nbsp; constexpr enum_table&amp; operator=3D(enum_ta=
ble&amp;&amp;) =3D default;</div></div><div><br></div><div>&nbsp; constexpr=
 const T&amp; operator[E tag] const;</div><div>&nbsp; constexpr bool lookup=
(const T&amp; value, E&amp; tag) const;</div><div>&nbsp; constexpr bool loo=
kup(T&amp;&amp; value, E&amp; tag) const;</div><div>&nbsp; constexpr size_t=
 size() const;</div><div><br></div><div>&nbsp; class iterator : std::bidire=
ctional_iterator&lt;<wbr>std::pair&lt;E, const T&amp;&gt;&gt; {};</div><div=
>&nbsp; class reverse_iterator;</div><div>&nbsp;&nbsp;</div><div>&nbsp; con=
stexpr iterator begin();</div><div>&nbsp; constexpr iterator end();</div><d=
iv><div>&nbsp; constexpr reverse_iterator rbegin();</div><div>&nbsp; conste=
xpr reverse_iterator rend();</div><div><br></div><div>&nbsp; constexpr iter=
ator find(E tag);</div><div>&nbsp; template &lt;typename Comparable&gt;</di=
v><div>&nbsp; constexpr iterator find(Comparable&amp;&amp; c); //lookup usi=
ng CMP(const T&amp;, C&amp;&amp;) or CMP(const T&amp;, const C&amp;) using =
perfect forwarding</div><div>&nbsp; constexpr iterator find(T&amp;&amp; val=
ue); //lookup using CMP()</div>};</div><div><br></div><div>template &lt;typ=
ename E&gt;</div><div>using enum_strtable =3D enum_table&lt;E, const char*,=
 [](const char* l, const char* r){ return strcmp(l, r) =3D=3D 0; }&gt;;</di=
v><div><br></div><div><br></div><div>//Usage</div><div>enum Color {<br>&nbs=
p; kRed,</div><div>&nbsp; kGreen,</div><div>&nbsp; kBlue</div><div>};</div>=
<div><br></div><div>//Could be place in binary .rodata section.</div><div>c=
onstexpr const enumstr_table&lt;Color&gt; color_tbl =3D { "Red", "Blue", "G=
reen" };</div><div><br></div><div>assert(!strcmp(color_tbl[kRed]<wbr>, "Red=
"));</div><div>assert(color_tbl.find("Red") !=3D color_tbl.end());</div><di=
v><br></div><div>I really want this for ubound, and loop(), and runtime str=
ing tables but while we're at it, there's a lot of cool stuff we could add.=
</div><div>Rationale here:</div><div><a href=3D"https://groups.google.com/f=
orum/#!searchin/comp.lang.c$2B$2B.moderated/enum/comp.lang.c++.moderated/Rp=
UiU9utY48/N-oUkAo5oIoJ" target=3D"_blank" onmousedown=3D"this.href=3D'https=
://groups.google.com/forum/#!searchin/comp.lang.c$2B$2B.moderated/enum/comp=
..lang.c++.moderated/RpUiU9utY48/N-oUkAo5oIoJ';return true;" onclick=3D"this=
..href=3D'https://groups.google.com/forum/#!searchin/comp.lang.c$2B$2B.moder=
ated/enum/comp.lang.c++.moderated/RpUiU9utY48/N-oUkAo5oIoJ';return true;">h=
ttps://groups.google.com/<wbr>forum/#!searchin/comp.lang.c$<wbr>2B$2B.moder=
ated/enum/comp.<wbr>lang.c++.moderated/<wbr>RpUiU9utY48/N-oUkAo5oIoJ</a><br=
></div><div><br></div><div>Other extensions I'd love to see:</div><div>* en=
um bitmasks as a real type, easy and expressive to declare, strict rules ab=
out logical operator comparisons. Only the tags in the enum can use binary =
logical operations with one another.</div><div>* concepts in the enum decla=
ration to enforce restrictions (is_contiguous, min =3D=3D 0, etc..)</div><d=
iv><br></div><div><br></div></div></blockquote></div></div></blockquote></d=
iv></div></blockquote></div></blockquote></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_2433_32256789.1389541290361--

.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Sun, 12 Jan 2014 17:56:52 +0200
Raw View
On 12 January 2014 17:41,  <inkwizytoryankes@gmail.com> wrote:
> Would be possible to create similar functionality for class? If this enum
> approach is possible to implement by every compiler, creating version for
> class should not be impossible.
> This would be more complex because class have private, static, unions,
> fields, base class, sub class and functions, but if we can made interface
> for one thing then creating for rest wouldnt be harder.


Short answer: yes, it's possible.

Longer answer: What SG7 (the Reclection Study Group) is more or less doing
is allowing things that an implementation knows, but the standard does not yet
specify, to be exposed to programmers in a hopefully portable fashion. This
likely includes information about which members a class has and where
they are. ;)

--

---
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: fmatthew5876@gmail.com
Date: Sun, 12 Jan 2014 09:00:17 -0800 (PST)
Raw View
------=_Part_395_6518421.1389546017040
Content-Type: text/plain; charset=ISO-8859-1

Check out the work being done for SG7.

https://groups.google.com/a/isocpp.org/forum/#!forum/reflection

This thread is specifically about enums.

On Sunday, January 12, 2014 10:41:30 AM UTC-5, inkwizyt...@gmail.com wrote:
>
> Would be possible to create similar functionality for class? If this enum
> approach is possible to implement by every compiler, creating version for
> class should not be impossible.
> This would be more complex because class have private, static, unions,
> fields, base class, sub class and functions, but if we can made interface
> for one thing then creating for rest wouldnt be harder.
>
> On Sunday, January 12, 2014 8:01:12 AM UTC+1, Andrew Tomazos wrote:
>>
>> So, first yes, my co-author Christian has written a reference
>> implementation that contains a superset of the N3815 proposed three
>> property queries.  You will find the link on the bottom of N3815.  This has
>> been forked and extended by Remotion (linked previously in this thread).
>>
>> But before you go diving into that and compiling custom implementation,
>> the three traits are really simple to understand and to mock up by hand
>> with an ordinary compiler:
>>
>> First recall the three property queries are:
>>
>>     enumerator_list_size<E> is the number of enumerators in the
>> enumeration E
>>     enumerator_value<E,I> is a value of type E that is the I'th
>> enumerator in declared order.
>>     enumerator_identifier<E,I> is a string literal with the identifier
>> of the I'th enumerator in declared order.
>>
>> So you can mock them up for experimentation "by hand" without compiler
>> changes as follows:
>>
>> First declare but don't define the three N3815 primaries...
>>
>>     template<typename E> struct enumerator_list_size;
>>     template<typename E, size_t I> struct enumerator_value;
>>     template<typename E, size_t I> struct enumerator_identifier;
>>
>> Then for each enumeration type in your test program, for example...
>>
>>     enum foo
>>     {
>>         bar,
>>         Baz,
>>         Qux = 42,
>>         Quux = 42,
>>     };
>>
>> ...manually define a set of specializations by hand as follows...
>>
>>     template<> struct enumerator_list_size<foo> { static constexpr size_t
>> value = 4; };
>>
>>     template<> struct enumerator_value<foo,0> { static constexpr foo
>> value = bar; };
>>     template<> struct enumerator_value<foo,1> { static constexpr foo
>> value = Baz; };
>>     template<> struct enumerator_value<foo,2> { static constexpr foo
>> value = Qux; };
>>     template<> struct enumerator_value<foo,3> { static constexpr foo
>> value = Quux; };
>>
>>     template<> struct enumerator_identifier<foo,0> { static constexpr
>> char value[4] = u8"bar"; };
>>     template<> struct enumerator_identifier<foo,1> { static constexpr
>> char value[4] = u8"Baz"; };
>>     template<> struct enumerator_identifier<foo,2> { static constexpr
>> char value[4] = u8"Qux"; };
>>     template<> struct enumerator_identifier<foo,3> { static constexpr
>> char value[5] = u8"Quux"; };
>>
>>     constexpr char enumerator_identifier<foo,0>::value[];
>>     constexpr char enumerator_identifier<foo,1>::value[];
>>     constexpr char enumerator_identifier<foo,2>::value[];
>>     constexpr char enumerator_identifier<foo,3>::value[];
>>
>> (The effect of N3815 is that these hand-written specializations will be
>> done automatically for you by the compiler when you use them.)
>>
>> Here is a complete self-contained compiling program with the above
>> integrated together you can copy and paste plus some tests:
>>
>>     #include <cassert>
>>     #include <cstddef>
>>     #include <string.h>
>>
>>     // N3815 primaries
>>     template<typename E> struct enumerator_list_size;
>>     template<typename E, size_t I> struct enumerator_value;
>>     template<typename E, size_t I> struct enumerator_identifier;
>>
>>     // your enumeration
>>     enum foo
>>     {
>>         bar,
>>         Baz,
>>         Qux = 42,
>>         Quux = 42,
>>     };
>>
>>     // define these specializations by hand:
>>     template<> struct enumerator_list_size<foo> { static constexpr size_t
>> value = 4; };
>>
>>     template<> struct enumerator_value<foo,0> { static constexpr foo
>> value = bar; };
>>     template<> struct enumerator_value<foo,1> { static constexpr foo
>> value = Baz; };
>>     template<> struct enumerator_value<foo,2> { static constexpr foo
>> value = Qux; };
>>     template<> struct enumerator_value<foo,3> { static constexpr foo
>> value = Quux; };
>>
>>     template<> struct enumerator_identifier<foo,0> { static constexpr
>> char value[4] = u8"bar"; };
>>     template<> struct enumerator_identifier<foo,1> { static constexpr
>> char value[4] = u8"Baz"; };
>>     template<> struct enumerator_identifier<foo,2> { static constexpr
>> char value[4] = u8"Qux"; };
>>     template<> struct enumerator_identifier<foo,3> { static constexpr
>> char value[5] = u8"Quux"; };
>>
>>     constexpr char enumerator_identifier<foo,0>::value[];
>>     constexpr char enumerator_identifier<foo,1>::value[];
>>     constexpr char enumerator_identifier<foo,2>::value[];
>>     constexpr char enumerator_identifier<foo,3>::value[];
>>
>>     // test they work:
>>     int main()
>>     {
>>         static_assert(enumerator_list_size<foo>::value == 4, "");
>>
>>         assert(strcmp(enumerator_identifier<foo,0>::value, u8"bar") == 0);
>>         assert(strcmp(enumerator_identifier<foo,1>::value, u8"Baz") == 0);
>>         assert(strcmp(enumerator_identifier<foo,2>::value, u8"Qux") == 0);
>>         assert(strcmp(enumerator_identifier<foo,3>::value, u8"Quux") ==
>> 0);
>>
>>         static_assert(enumerator_value<foo,0>::value == bar, "");
>>         static_assert(enumerator_value<foo,1>::value == Baz, "");
>>         static_assert(enumerator_value<foo,2>::value == Qux, "");
>>         static_assert(enumerator_value<foo,3>::value == Quux, "");
>>
>>         constexpr const char* str = enumerator_identifier<foo,0>::value;
>>         static_assert(str[0] == 'b', "");
>>         static_assert(str[1] == 'a', "");
>>         static_assert(str[2] == 'r', "");
>>         static_assert(str[3] == '\0', "");
>>     }
>>
>> Enjoy,
>> Andrew.
>>
>>
>> On Sunday, January 12, 2014 6:16:52 AM UTC+1, fmatth...@gmail.com wrote:
>>>
>>> Sure, is there a working implementation of your proposal? I don't have a
>>> lot of free time so it will be slow, but I can take a look. If so, I might
>>> like to help work on the library features that come after your proposal.
>>>
>>> The list I made is a general sketch of some of the things I think might
>>> be immediatly useful. Many of these I already do manually using crude
>>> interfaces now. It will take some time to come up with a solid library
>>> design with a correctly chosen and designed features.
>>>
>>>
>>>
>>> On Saturday, January 11, 2014 11:39:50 PM UTC-5, Andrew Tomazos wrote:
>>>>
>>>> Could you please review N3815 (
>>>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3815.html) and
>>>> confirm that you can implement your enum_traits and enum_table class as a
>>>> pure library feature on top of the three provided type traits, and that the
>>>> solution would be as efficient as if the compiler did it for you?
>>>>
>>>> If you are unsure or think you have a feature you want that could not
>>>> be implemented on top of the N3815 type traits as an efficient pure library
>>>> feature, could you please point it out?
>>>>
>>>> Our current plan is to standardize N3815 in the Library Fundamentals TS
>>>> as a minmal complete interface that enables library / framework authors to
>>>> provide all this functionality that you want.
>>>>
>>>> From a review of your enum_traits and enum_table class I believe that
>>>> this is indeed the case - that both could all be built efficiently as a
>>>> pure library solution on top of the N3815.  Could you see if you agree.
>>>>
>>>> Thanks,
>>>> Andrew.
>>>>
>>>>
>>>>
>>>> On Saturday, January 11, 2014 7:47:48 AM UTC+1, fmatth...@gmail.comwrote:
>>>>>
>>>>> Enums are one of my favorite tools for efficently labeling
>>>>> collections, but we need to be able to query more information about them.
>>>>>
>>>>> I'd like to suggest some form of enum traits.
>>>>>
>>>>> template <typename E>
>>>>> struct enum_traits<E> {
>>>>>   static_assert(is_enum<E>::value, "Only valid for enums!");
>>>>>
>>>>>   typedef /* underlying type */ value_type;
>>>>>   static constexpr const value_type min = /* minimum value of enum */
>>>>>   static constexpr const value_type max = /* maximum value of enum */
>>>>>   static constexpr const value_type ubound = /* maximum value of
>>>>> enum+1. Not present (does not compile if queried) if max ==
>>>>> numeric_limits<value_type>::max(). (Note: this is the most useful value)*/
>>>>>
>>>>>   static constexpr const size_t count = /* Number of enum tags */
>>>>>   static constexpr const size_t distinct = /* Number of enum tags with
>>>>> distinct values */
>>>>>   static constexpr const bool is_contiguious = /* true if enum values
>>>>> are contiguous */
>>>>>   static constexpr const bool is_regular = is_contiguous && min ==
>>>>> value_type(0);
>>>>>   static constexpr const bool has_zero = /* true if zero is an enum
>>>>> value */
>>>>>   static constexpr const bool has_postive = /* true if at least one
>>>>> enum value is positive */
>>>>>   static constexpr const bool all_postive = /* true if all enum values
>>>>> are positive */
>>>>>   static constexpr const bool has_negative = /* true if at least one
>>>>> enum value is negative */
>>>>>   static constexpr const bool all_negative = /* true if all enum
>>>>> values are negative */
>>>>>
>>>>> //Utilities to enable foreach, compiler generated
>>>>>   class iterator : public std::bidirectional_iterator<E> {
>>>>>     public:
>>>>>       E operator*();
>>>>>       //iterator stuff, operator++ goes to next enum value in
>>>>> operator<() order.
>>>>>   };
>>>>>   class reverse_iterator;
>>>>>   struct range {
>>>>>
>>>>>     iterator begin();
>>>>>     iterator end();
>>>>>
>>>>>     reverse_iterator rbegin();
>>>>>     reverse_iterator rend();
>>>>>   };
>>>>>
>>>>>   range<E> loop();
>>>>> };
>>>>>
>>>>> //foreach loop over enum values
>>>>> for(auto e : enum_traits<E>::loop()) {
>>>>> };
>>>>>
>>>>> //Create tables keyed by enums, standard library component
>>>>> template <typename E, typename T, typename CMP = std::equal_to>
>>>>> class enum_table {
>>>>>   //static asserts if li.size() != enum_traits<E>::distinct;
>>>>>   constexpr enum_table(std::initializer_list<T> li);
>>>>>   constexpr enum_table(const enum_table&) = default;
>>>>>   constexpr enum_table(enum_table&&) = default;
>>>>>   constexpr enum_table& operator=(const enum_table&) = default;
>>>>>   constexpr enum_table& operator=(enum_table&&) = default;
>>>>>
>>>>>   constexpr const T& operator[E tag] const;
>>>>>   constexpr bool lookup(const T& value, E& tag) const;
>>>>>   constexpr bool lookup(T&& value, E& tag) const;
>>>>>   constexpr size_t size() const;
>>>>>
>>>>>   class iterator : std::bidirectional_iterator<std::pair<E, const T&>>
>>>>> {};
>>>>>   class reverse_iterator;
>>>>>
>>>>>   constexpr iterator begin();
>>>>>   constexpr iterator end();
>>>>>   constexpr reverse_iterator rbegin();
>>>>>   constexpr reverse_iterator rend();
>>>>>
>>>>>   constexpr iterator find(E tag);
>>>>>   template <typename Comparable>
>>>>>   constexpr iterator find(Comparable&& c); //lookup using CMP(const
>>>>> T&, C&&) or CMP(const T&, const C&) using perfect forwarding
>>>>>   constexpr iterator find(T&& value); //lookup using CMP()
>>>>> };
>>>>>
>>>>> template <typename E>
>>>>> using enum_strtable = enum_table<E, const char*, [](const char* l,
>>>>> const char* r){ return strcmp(l, r) == 0; }>;
>>>>>
>>>>>
>>>>> //Usage
>>>>> enum Color {
>>>>>   kRed,
>>>>>   kGreen,
>>>>>   kBlue
>>>>> };
>>>>>
>>>>> //Could be place in binary .rodata section.
>>>>> constexpr const enumstr_table<Color> color_tbl = { "Red", "Blue",
>>>>> "Green" };
>>>>>
>>>>> assert(!strcmp(color_tbl[kRed], "Red"));
>>>>> assert(color_tbl.find("Red") != color_tbl.end());
>>>>>
>>>>> I really want this for ubound, and loop(), and runtime string tables
>>>>> but while we're at it, there's a lot of cool stuff we could add.
>>>>> Rationale here:
>>>>>
>>>>> https://groups.google.com/forum/#!searchin/comp.lang.c$2B$2B.moderated/enum/comp.lang.c++.moderated/RpUiU9utY48/N-oUkAo5oIoJ
>>>>>
>>>>> Other extensions I'd love to see:
>>>>> * enum bitmasks as a real type, easy and expressive to declare, strict
>>>>> rules about logical operator comparisons. Only the tags in the enum can use
>>>>> binary logical operations with one another.
>>>>> * concepts in the enum declaration to enforce restrictions
>>>>> (is_contiguous, min == 0, etc..)
>>>>>
>>>>>
>>>>>

--

---
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_395_6518421.1389546017040
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Check out the work being done for SG7.&nbsp;<div><br></div=
><div><a href=3D"https://groups.google.com/a/isocpp.org/forum/#!forum/refle=
ction">https://groups.google.com/a/isocpp.org/forum/#!forum/reflection</a><=
br></div><div><br></div><div>This thread is specifically about enums.<br><b=
r>On Sunday, January 12, 2014 10:41:30 AM UTC-5, inkwizyt...@gmail.com wrot=
e:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">Would be po=
ssible to create similar functionality for class? If this enum approach is =
possible to implement by every compiler, creating version for class should =
not be impossible.<br>This would be more complex because class have private=
, static, unions, fields, base class, sub class and functions, but if we ca=
n made interface for one thing then creating for rest wouldnt be harder.<br=
><br>On Sunday, January 12, 2014 8:01:12 AM UTC+1, Andrew Tomazos wrote:<bl=
ockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-l=
eft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>So, first yes, m=
y co-author Christian has written a reference implementation that contains =
a superset of the N3815 proposed three property queries. &nbsp;You will fin=
d the link on the bottom of N3815. &nbsp;This has been forked and extended =
by Remotion (linked previously in this thread).</div><div><br></div><div>Bu=
t before you go diving into that and compiling custom implementation, the t=
hree traits are really simple to understand and to mock up by hand with an =
ordinary compiler:</div><div><br></div><div>First recall the three property=
 queries are:</div><div><br></div><div>&nbsp; &nbsp; <font face=3D"courier =
new, monospace">enumerator_list_size&lt;E&gt;</font> is the number of enume=
rators in the enumeration E</div><div>&nbsp; &nbsp; <font face=3D"courier n=
ew, monospace">enumerator_value&lt;E,I&gt;</font> is a value of type E that=
 is the I'th enumerator in declared order.</div><div>&nbsp; &nbsp; <font fa=
ce=3D"courier new, monospace">enumerator_identifier&lt;E,I&gt;</font> is a =
string literal with the identifier of the I'th enumerator in declared order=
..</div><div><br></div><div>So you can mock them up for experimentation "by =
hand" without compiler changes as follows:</div><div><br></div><div>First d=
eclare but don't define the three N3815 primaries...</div><div><br></div><d=
iv><font face=3D"courier new, monospace">&nbsp; &nbsp; template&lt;typename=
 E&gt; struct enumerator_list_size;</font></div><div><font face=3D"courier =
new, monospace">&nbsp; &nbsp; template&lt;typename E, size_t I&gt; struct e=
numerator_value;</font></div><div><font face=3D"courier new, monospace">&nb=
sp; &nbsp; template&lt;typename E, size_t I&gt; struct enumerator_identifie=
r;</font></div><div><br></div><div>Then for each enumeration type in your t=
est program, for example...</div><div><br></div><div><font face=3D"courier =
new, monospace">&nbsp; &nbsp; enum foo</font></div><div><font face=3D"couri=
er new, monospace">&nbsp; &nbsp; {</font></div><div><font face=3D"courier n=
ew, monospace">&nbsp; &nbsp; &nbsp; &nbsp; bar,</font></div><div><font face=
=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; Baz,</font></div><d=
iv><font face=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; Qux =
=3D 42,</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp=
; &nbsp; &nbsp; Quux =3D 42,</font></div><div><font face=3D"courier new, mo=
nospace">&nbsp; &nbsp; };</font></div><div><br></div><div>...manually defin=
e a set of specializations by hand as follows...</div><div><br></div><div><=
font face=3D"courier new, monospace">&nbsp; &nbsp; template&lt;&gt; struct =
enumerator_list_size&lt;foo&gt; { static constexpr size_t value =3D 4; };</=
font></div><div><font face=3D"courier new, monospace"><br></font></div><div=
><font face=3D"courier new, monospace">&nbsp; &nbsp; template&lt;&gt; struc=
t enumerator_value&lt;foo,0&gt; { static constexpr foo value =3D bar; };</f=
ont></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; template=
&lt;&gt; struct enumerator_value&lt;foo,1&gt; { static constexpr foo value =
=3D Baz; };</font></div><div><font face=3D"courier new, monospace">&nbsp; &=
nbsp; template&lt;&gt; struct enumerator_value&lt;foo,2&gt; { static conste=
xpr foo value =3D Qux; };</font></div><div><font face=3D"courier new, monos=
pace">&nbsp; &nbsp; template&lt;&gt; struct enumerator_value&lt;foo,3&gt; {=
 static constexpr foo value =3D Quux; };</font></div><div><font face=3D"cou=
rier new, monospace"><br></font></div><div><font face=3D"courier new, monos=
pace">&nbsp; &nbsp; template&lt;&gt; struct enumerator_identifier&lt;foo,0&=
gt; { static constexpr char value[4] =3D u8"bar"; };</font></div><div><font=
 face=3D"courier new, monospace">&nbsp; &nbsp; template&lt;&gt; struct enum=
erator_identifier&lt;foo,1&gt; { static constexpr char value[4] =3D u8"Baz"=
; };</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; t=
emplate&lt;&gt; struct enumerator_identifier&lt;foo,2&gt; { static constexp=
r char value[4] =3D u8"Qux"; };</font></div><div><font face=3D"courier new,=
 monospace">&nbsp; &nbsp; template&lt;&gt; struct enumerator_identifier&lt;=
foo,3&gt; { static constexpr char value[5] =3D u8"Quux"; };</font></div><di=
v><font face=3D"courier new, monospace"><br></font></div><div><font face=3D=
"courier new, monospace">&nbsp; &nbsp; constexpr char enumerator_identifier=
&lt;foo,0&gt;::<wbr>value[];</font></div><div><font face=3D"courier new, mo=
nospace">&nbsp; &nbsp; constexpr char enumerator_identifier&lt;foo,1&gt;::<=
wbr>value[];</font></div><div><font face=3D"courier new, monospace">&nbsp; =
&nbsp; constexpr char enumerator_identifier&lt;foo,2&gt;::<wbr>value[];</fo=
nt></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; constexpr=
 char enumerator_identifier&lt;foo,3&gt;::<wbr>value[];</font></div><div><b=
r></div><div>(The effect of N3815 is that these hand-written specialization=
s will be done automatically for you by the compiler when you use them.)</d=
iv><div><br></div><div>Here is a complete self-contained compiling program =
with the above integrated together you can copy and paste plus some tests:<=
/div><div><br></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp=
; #include &lt;cassert&gt;</font></div><div><font face=3D"courier new, mono=
space">&nbsp; &nbsp; #include &lt;cstddef&gt;</font></div><div><font face=
=3D"courier new, monospace">&nbsp; &nbsp; #include &lt;string.h&gt;</font><=
/div><div><font face=3D"courier new, monospace"><br></font></div><div><font=
 face=3D"courier new, monospace">&nbsp; &nbsp; // N3815 primaries</font></d=
iv><div><font face=3D"courier new, monospace">&nbsp; &nbsp; template&lt;typ=
ename E&gt; struct enumerator_list_size;</font></div><div><font face=3D"cou=
rier new, monospace">&nbsp; &nbsp; template&lt;typename E, size_t I&gt; str=
uct enumerator_value;</font></div><div><font face=3D"courier new, monospace=
">&nbsp; &nbsp; template&lt;typename E, size_t I&gt; struct enumerator_iden=
tifier;</font></div><div><font face=3D"courier new, monospace"><br></font><=
/div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; // your enume=
ration</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp;=
 enum foo</font></div><div><font face=3D"courier new, monospace">&nbsp; &nb=
sp; {</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; =
&nbsp; &nbsp; bar,</font></div><div><font face=3D"courier new, monospace">&=
nbsp; &nbsp; &nbsp; &nbsp; Baz,</font></div><div><font face=3D"courier new,=
 monospace">&nbsp; &nbsp; &nbsp; &nbsp; Qux =3D 42,</font></div><div><font =
face=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; Quux =3D 42,</f=
ont></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; };</font=
></div><div><font face=3D"courier new, monospace"><br></font></div><div><fo=
nt face=3D"courier new, monospace">&nbsp; &nbsp; // define these specializa=
tions by hand:</font></div><div><font face=3D"courier new, monospace">&nbsp=
; &nbsp; template&lt;&gt; struct enumerator_list_size&lt;foo&gt; { static c=
onstexpr size_t value =3D 4; };</font></div><div><font face=3D"courier new,=
 monospace"><br></font></div><div><font face=3D"courier new, monospace">&nb=
sp; &nbsp; template&lt;&gt; struct enumerator_value&lt;foo,0&gt; { static c=
onstexpr foo value =3D bar; };</font></div><div><font face=3D"courier new, =
monospace">&nbsp; &nbsp; template&lt;&gt; struct enumerator_value&lt;foo,1&=
gt; { static constexpr foo value =3D Baz; };</font></div><div><font face=3D=
"courier new, monospace">&nbsp; &nbsp; template&lt;&gt; struct enumerator_v=
alue&lt;foo,2&gt; { static constexpr foo value =3D Qux; };</font></div><div=
><font face=3D"courier new, monospace">&nbsp; &nbsp; template&lt;&gt; struc=
t enumerator_value&lt;foo,3&gt; { static constexpr foo value =3D Quux; };</=
font></div><div><font face=3D"courier new, monospace"><br></font></div><div=
><font face=3D"courier new, monospace">&nbsp; &nbsp; template&lt;&gt; struc=
t enumerator_identifier&lt;foo,0&gt; { static constexpr char value[4] =3D u=
8"bar"; };</font></div><div><font face=3D"courier new, monospace">&nbsp; &n=
bsp; template&lt;&gt; struct enumerator_identifier&lt;foo,1&gt; { static co=
nstexpr char value[4] =3D u8"Baz"; };</font></div><div><font face=3D"courie=
r new, monospace">&nbsp; &nbsp; template&lt;&gt; struct enumerator_identifi=
er&lt;foo,2&gt; { static constexpr char value[4] =3D u8"Qux"; };</font></di=
v><div><font face=3D"courier new, monospace">&nbsp; &nbsp; template&lt;&gt;=
 struct enumerator_identifier&lt;foo,3&gt; { static constexpr char value[5]=
 =3D u8"Quux"; };</font></div><div><font face=3D"courier new, monospace"><b=
r></font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; con=
stexpr char enumerator_identifier&lt;foo,0&gt;::<wbr>value[];</font></div><=
div><font face=3D"courier new, monospace">&nbsp; &nbsp; constexpr char enum=
erator_identifier&lt;foo,1&gt;::<wbr>value[];</font></div><div><font face=
=3D"courier new, monospace">&nbsp; &nbsp; constexpr char enumerator_identif=
ier&lt;foo,2&gt;::<wbr>value[];</font></div><div><font face=3D"courier new,=
 monospace">&nbsp; &nbsp; constexpr char enumerator_identifier&lt;foo,3&gt;=
::<wbr>value[];</font></div><div><font face=3D"courier new, monospace"><br>=
</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; // te=
st they work:</font></div><div><font face=3D"courier new, monospace">&nbsp;=
 &nbsp; int main()</font></div><div><font face=3D"courier new, monospace">&=
nbsp; &nbsp; {</font></div><div><font face=3D"courier new, monospace">&nbsp=
; &nbsp; &nbsp; &nbsp; static_assert(enumerator_list_<wbr>size&lt;foo&gt;::=
value =3D=3D 4, "");</font></div><div><font face=3D"courier new, monospace"=
><br></font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; =
&nbsp; &nbsp; assert(strcmp(enumerator_<wbr>identifier&lt;foo,0&gt;::value,=
 u8"bar") =3D=3D 0);</font></div><div><font face=3D"courier new, monospace"=
>&nbsp; &nbsp; &nbsp; &nbsp; assert(strcmp(enumerator_<wbr>identifier&lt;fo=
o,1&gt;::value, u8"Baz") =3D=3D 0);</font></div><div><font face=3D"courier =
new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; assert(strcmp(enumerator_<wbr>i=
dentifier&lt;foo,2&gt;::value, u8"Qux") =3D=3D 0);</font></div><div><font f=
ace=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; assert(strcmp(en=
umerator_<wbr>identifier&lt;foo,3&gt;::value, u8"Quux") =3D=3D 0);</font></=
div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp;<=
/font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; &nbsp;=
 &nbsp; static_assert(enumerator_<wbr>value&lt;foo,0&gt;::value =3D=3D bar,=
 "");</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; =
&nbsp; &nbsp; static_assert(enumerator_<wbr>value&lt;foo,1&gt;::value =3D=
=3D Baz, "");</font></div><div><font face=3D"courier new, monospace">&nbsp;=
 &nbsp; &nbsp; &nbsp; static_assert(enumerator_<wbr>value&lt;foo,2&gt;::val=
ue =3D=3D Qux, "");</font></div><div><font face=3D"courier new, monospace">=
&nbsp; &nbsp; &nbsp; &nbsp; static_assert(enumerator_<wbr>value&lt;foo,3&gt=
;::value =3D=3D Quux, "");</font></div><div><font face=3D"courier new, mono=
space">&nbsp; &nbsp; &nbsp; &nbsp;</font></div><div><font face=3D"courier n=
ew, monospace">&nbsp; &nbsp; &nbsp; &nbsp; constexpr const char* str =3D en=
umerator_identifier&lt;foo,0&gt;::<wbr>value;</font></div><div><font face=
=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; static_assert(str[0=
] =3D=3D 'b', "");</font></div><div><font face=3D"courier new, monospace">&=
nbsp; &nbsp; &nbsp; &nbsp; static_assert(str[1] =3D=3D 'a', "");</font></di=
v><div><font face=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; st=
atic_assert(str[2] =3D=3D 'r', "");</font></div><div><font face=3D"courier =
new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; static_assert(str[3] =3D=3D '\0=
', "");</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp=
; }</font></div><div><br></div><div>Enjoy,</div><div>Andrew.</div><div><br>=
</div><br>On Sunday, January 12, 2014 6:16:52 AM UTC+1, <a>fmatth...@gmail.=
com</a> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-le=
ft:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">Sure=
, is there a working implementation of your proposal? I don't have a lot of=
 free time so it will be slow, but I can take a look. If so, I might like t=
o help work on the library features that come after your proposal.&nbsp;<di=
v><br></div><div>The list I made is a general sketch of some of the things =
I think might be immediatly useful. Many of these I already do manually usi=
ng crude interfaces now. It will take some time to come up with a solid lib=
rary design with a correctly chosen and designed features.</div><div><br></=
div><div><br><br>On Saturday, January 11, 2014 11:39:50 PM UTC-5, Andrew To=
mazos 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">Could =
you please review N3815 (<a href=3D"http://www.open-std.org/jtc1/sc22/wg21/=
docs/papers/2013/n3815.html" target=3D"_blank" onmousedown=3D"this.href=3D'=
http://www.google.com/url?q\75http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2=
Fwg21%2Fdocs%2Fpapers%2F2013%2Fn3815.html\46sa\75D\46sntz\0751\46usg\75AFQj=
CNHwe7liqoidkU5rvKFSWklGuTd4gw';return true;" onclick=3D"this.href=3D'http:=
//www.google.com/url?q\75http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21=
%2Fdocs%2Fpapers%2F2013%2Fn3815.html\46sa\75D\46sntz\0751\46usg\75AFQjCNHwe=
7liqoidkU5rvKFSWklGuTd4gw';return true;">http://www.open-std.org/jtc1/<wbr>=
sc22/wg21/docs/papers/2013/<wbr>n3815.html</a>)&nbsp;and confirm that you c=
an implement your enum_traits and enum_table class as a pure library featur=
e on top of the three provided type traits, and that the solution would be =
as efficient as if the compiler did it for you?<div><br></div><div>If you a=
re unsure or think you have a feature you want that could not be implemente=
d on top of the N3815 type traits as an efficient pure library feature, cou=
ld you please point it out?</div><div><br></div><div>Our current plan is to=
 standardize N3815 in the Library Fundamentals TS as a minmal complete inte=
rface that enables library / framework authors to provide all this function=
ality that you want.</div><div><br></div><div>From a review of your enum_tr=
aits and enum_table class I believe that this is indeed the case - that bot=
h could all be built efficiently as a pure library solution on top of the N=
3815. &nbsp;Could you see if you agree.<br><br>Thanks,</div><div>Andrew.</d=
iv><div><br><br><br>On Saturday, January 11, 2014 7:47:48 AM UTC+1, <a>fmat=
th...@gmail.com</a> 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">Enums are one of my favorite tools for efficently labeling collect=
ions, but we need to be able to query more information about them.<div><br>=
</div><div>I'd like to suggest some form of enum traits.&nbsp;</div><div><b=
r></div><div>template &lt;typename E&gt;</div><div>struct enum_traits&lt;E&=
gt; {</div><div>&nbsp; static_assert(is_enum&lt;E&gt;::<wbr>value, "Only va=
lid for enums!");</div><div>&nbsp;&nbsp;</div><div>&nbsp; typedef /* underl=
ying type */ value_type;</div><div>&nbsp; static constexpr const value_type=
 min =3D /* minimum value of enum */</div><div>&nbsp; static constexpr cons=
t value_type max =3D /* maximum value of enum */</div><div>&nbsp; static co=
nstexpr const value_type ubound =3D /* maximum value of enum+1. Not present=
 (does not compile if queried) if max =3D=3D numeric_limits&lt;value_type&g=
t;::<wbr>max(). (Note: this is the most useful value)*/</div><div><br></div=
><div>&nbsp; static constexpr const size_t count =3D /* Number of enum tags=
 */</div><div>&nbsp; static constexpr const size_t distinct =3D /* Number o=
f enum tags with distinct values */&nbsp;</div><div>&nbsp; static constexpr=
 const bool is_contiguious =3D /* true if enum values are contiguous */</di=
v><div>&nbsp; static constexpr const bool is_regular =3D is_contiguous &amp=
;&amp; min =3D=3D value_type(0);</div><div>&nbsp; static constexpr const bo=
ol has_zero =3D /* true if zero is an enum value */</div><div>&nbsp; static=
 constexpr const bool has_postive =3D /* true if at least one enum value is=
 positive */</div><div>&nbsp; static constexpr const bool all_postive =3D /=
* true if all enum values are positive */</div><div>&nbsp; static constexpr=
 const bool has_negative =3D /* true if at least one enum value is negative=
 */</div><div>&nbsp; static constexpr const bool all_negative =3D /* true i=
f all enum values are negative */</div><div><br></div><div>//Utilities to e=
nable foreach, compiler generated</div><div>&nbsp; class iterator : public =
std::bidirectional_iterator&lt;E&gt; {</div><div>&nbsp; &nbsp; public:</div=
><div>&nbsp; &nbsp; &nbsp; E operator*();</div><div>&nbsp; &nbsp; &nbsp; //=
iterator stuff, operator++ goes to next enum value in operator&lt;() order.=
</div><div>&nbsp; };</div><div>&nbsp; class reverse_iterator;</div><div>&nb=
sp; struct range {</div><div><br></div><div>&nbsp; &nbsp; iterator begin();=
</div><div>&nbsp; &nbsp; iterator end();</div><div><br></div><div>&nbsp; &n=
bsp; reverse_iterator rbegin();</div><div>&nbsp; &nbsp; reverse_iterator re=
nd();<br>&nbsp; };</div><div><br></div><div>&nbsp; range&lt;E&gt; loop();</=
div><div>};</div><div><br></div><div>//foreach loop over enum values</div><=
div>for(auto e : enum_traits&lt;E&gt;::loop()) {<br>};</div><div><br></div>=
<div>//Create tables keyed by enums, standard library component</div><div>t=
emplate &lt;typename E, typename T, typename CMP =3D std::equal_to&gt;</div=
><div>class enum_table {</div><div>&nbsp; //static asserts if li.size() !=
=3D enum_traits&lt;E&gt;::distinct;</div><div>&nbsp; constexpr enum_table(s=
td::initializer_<wbr>list&lt;T&gt; li);</div><div>&nbsp; constexpr enum_tab=
le(const enum_table&amp;) =3D default;</div><div>&nbsp; constexpr enum_tabl=
e(enum_table&amp;&amp;) =3D default;</div><div><div>&nbsp; constexpr enum_t=
able&amp; operator=3D(const enum_table&amp;) =3D default;</div><div>&nbsp; =
constexpr enum_table&amp; operator=3D(enum_table&amp;&amp;) =3D default;</d=
iv></div><div><br></div><div>&nbsp; constexpr const T&amp; operator[E tag] =
const;</div><div>&nbsp; constexpr bool lookup(const T&amp; value, E&amp; ta=
g) const;</div><div>&nbsp; constexpr bool lookup(T&amp;&amp; value, E&amp; =
tag) const;</div><div>&nbsp; constexpr size_t size() const;</div><div><br><=
/div><div>&nbsp; class iterator : std::bidirectional_iterator&lt;<wbr>std::=
pair&lt;E, const T&amp;&gt;&gt; {};</div><div>&nbsp; class reverse_iterator=
;</div><div>&nbsp;&nbsp;</div><div>&nbsp; constexpr iterator begin();</div>=
<div>&nbsp; constexpr iterator end();</div><div><div>&nbsp; constexpr rever=
se_iterator rbegin();</div><div>&nbsp; constexpr reverse_iterator rend();</=
div><div><br></div><div>&nbsp; constexpr iterator find(E tag);</div><div>&n=
bsp; template &lt;typename Comparable&gt;</div><div>&nbsp; constexpr iterat=
or find(Comparable&amp;&amp; c); //lookup using CMP(const T&amp;, C&amp;&am=
p;) or CMP(const T&amp;, const C&amp;) using perfect forwarding</div><div>&=
nbsp; constexpr iterator find(T&amp;&amp; value); //lookup using CMP()</div=
>};</div><div><br></div><div>template &lt;typename E&gt;</div><div>using en=
um_strtable =3D enum_table&lt;E, const char*, [](const char* l, const char*=
 r){ return strcmp(l, r) =3D=3D 0; }&gt;;</div><div><br></div><div><br></di=
v><div>//Usage</div><div>enum Color {<br>&nbsp; kRed,</div><div>&nbsp; kGre=
en,</div><div>&nbsp; kBlue</div><div>};</div><div><br></div><div>//Could be=
 place in binary .rodata section.</div><div>constexpr const enumstr_table&l=
t;Color&gt; color_tbl =3D { "Red", "Blue", "Green" };</div><div><br></div><=
div>assert(!strcmp(color_tbl[kRed]<wbr>, "Red"));</div><div>assert(color_tb=
l.find("Red") !=3D color_tbl.end());</div><div><br></div><div>I really want=
 this for ubound, and loop(), and runtime string tables but while we're at =
it, there's a lot of cool stuff we could add.</div><div>Rationale here:</di=
v><div><a href=3D"https://groups.google.com/forum/#!searchin/comp.lang.c$2B=
$2B.moderated/enum/comp.lang.c++.moderated/RpUiU9utY48/N-oUkAo5oIoJ" target=
=3D"_blank" onmousedown=3D"this.href=3D'https://groups.google.com/forum/#!s=
earchin/comp.lang.c$2B$2B.moderated/enum/comp.lang.c++.moderated/RpUiU9utY4=
8/N-oUkAo5oIoJ';return true;" onclick=3D"this.href=3D'https://groups.google=
..com/forum/#!searchin/comp.lang.c$2B$2B.moderated/enum/comp.lang.c++.modera=
ted/RpUiU9utY48/N-oUkAo5oIoJ';return true;">https://groups.google.com/<wbr>=
forum/#!searchin/comp.lang.c$<wbr>2B$2B.moderated/enum/comp.<wbr>lang.c++.m=
oderated/<wbr>RpUiU9utY48/N-oUkAo5oIoJ</a><br></div><div><br></div><div>Oth=
er extensions I'd love to see:</div><div>* enum bitmasks as a real type, ea=
sy and expressive to declare, strict rules about logical operator compariso=
ns. Only the tags in the enum can use binary logical operations with one an=
other.</div><div>* concepts in the enum declaration to enforce restrictions=
 (is_contiguous, min =3D=3D 0, etc..)</div><div><br></div><div><br></div></=
div></blockquote></div></div></blockquote></div></div></blockquote></div></=
blockquote></div></blockquote></div></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_395_6518421.1389546017040--

.


Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Sun, 12 Jan 2014 17:08:45 -0800 (PST)
Raw View
------=_Part_589_21462569.1389575325737
Content-Type: text/plain; charset=ISO-8859-1

On Sunday, January 12, 2014 4:41:30 PM UTC+1, inkwizyt...@gmail.com wrote:
>
> Would be possible to create similar functionality for class? If this enum
> approach is possible to implement by every compiler, creating version for
> class should not be impossible.
>

If I can fit a mouse in my pocket, I must be able to fit an elephant too,
because they are both animals.  Also known as a hasty generalization.

Enumeration types are just a multiset of named integral constants where the
names are always identifiers.  We will support complete efficient
reflection of enumeration types with the three N3815 type traits as a tiny
extension to that existing library.  The additional standard wording to
specify them was only 50 words.

This would be more complex because class have private, static, unions,
> fields, base class, sub class and functions, but if we can made interface
> for one thing then creating for rest wouldnt be harder.
>

You've massively understated the difference in complexity between
enumeration types and class types.

Enumeration types are specified by 4 pages in the standard (7.2)

Class types are specified by 69 pages (clauses 9, 10, 11, 12) even if you
handwaive the fact that they can contain member templates (an additional 74
pages).

Having said that the reference implementation of N3815 does also include a
bunch of additional intrinsics to perform some forms of class type
reflection, but nothing we are proposing for standardization.

On top of the sheer difficulty of designing a complete standard schema for
class types that the compiler should expose, we also have the problem that
the C++ language isn't there yet in being able to handle the complexity of
such a schema at compile-time.  At compile-time you have to model the
schema using some combination of literal types, constant expressions,
constexpr functions and template-metaprogramming.  The type traits approach
chokes on the complexity at this point.  For a sane approach we really need
basic primitives like dynamic memory and polymorphic types like the
compiler itself uses internally to describe the model, but these are not
yet available during translation in C++.

I do have some rough designs for a larger extensible C++ reflection
framework that would include class types.  It works with opaque handles and
a couple of new core language operators called reflect and reify, but it
would be something for C++17 at the earliest if it works out at all.

--

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

------=_Part_589_21462569.1389575325737
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>On Sunday, January 12, 2014 4:41:30 PM UTC+1, inkwizy=
t...@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0px=
 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 20=
4); border-left-style: solid; padding-left: 1ex;"><div dir=3D"ltr">Would be=
 possible to create similar functionality for class? If this enum approach =
is possible to implement by every compiler, creating version for class shou=
ld not be impossible.<br></div></blockquote><div>&nbsp;</div></div>If I can=
 fit a mouse in my pocket, I must be able to fit an elephant too, because t=
hey are both animals. &nbsp;Also known as a hasty generalization.<div><br><=
/div><div>Enumeration types are just a multiset of named integral constants=
 where the names are always identifiers. &nbsp;We will support complete eff=
icient reflection of enumeration types with the three N3815 type traits as =
a tiny extension to that existing library. &nbsp;The additional standard wo=
rding to specify them was only 50 words.</div><div><br></div><div><blockquo=
te class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; border-left-wi=
dth: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; =
padding-left: 1ex;"><div dir=3D"ltr">This would be more complex because cla=
ss have private, static, unions, fields, base class, sub class and function=
s, but if we can made interface for one thing then creating for rest wouldn=
t be harder.</div></blockquote><div><br></div><div>You've massively underst=
ated the difference in complexity between enumeration types and class types=
..</div><div><br></div></div><div>Enumeration types are specified by 4 pages=
 in the standard (7.2)</div><div><br></div><div>Class types are specified b=
y 69 pages (clauses 9, 10, 11, 12) even if you handwaive the fact that they=
 can contain member templates (an additional 74 pages).</div><div><br></div=
><div>Having said that the reference implementation of N3815 does also incl=
ude a bunch of additional intrinsics to perform some forms of class type re=
flection, but nothing we are proposing for standardization.</div><div><br><=
/div><div>On top of the sheer difficulty of designing a complete standard s=
chema for class types that the compiler should expose, we also have the pro=
blem that the C++ language isn't there yet in being able to handle the comp=
lexity of such a schema at compile-time. &nbsp;At compile-time you have to =
model the schema using some combination of literal types, constant expressi=
ons, constexpr functions and template-metaprogramming. &nbsp;The type trait=
s approach chokes on the complexity at this point. &nbsp;For a sane approac=
h we really need basic primitives like dynamic memory and polymorphic types=
 like the compiler itself uses internally to describe the model, but these =
are not yet available during translation in C++.</div><div><br></div><div>I=
 do have some rough designs for a larger extensible C++ reflection framewor=
k that would include class types. &nbsp;It works with opaque handles and a =
couple of new core language operators called reflect and reify, but it woul=
d be something for C++17 at the earliest if it works out at all.</div><div>=
<br></div></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_589_21462569.1389575325737--

.


Author: Matthew Woehlke <mw_triad@users.sourceforge.net>
Date: Mon, 13 Jan 2014 13:13:37 -0500
Raw View
On 2014-01-11 01:47, fmatthew5876@gmail.com wrote:
> Enums are one of my favorite tools for efficently labeling collections, but
> we need to be able to query more information about them.
>
> I'd like to suggest some form of enum traits.
>
> template <typename E>
> struct enum_traits<E> {
>    static_assert(is_enum<E>::value, "Only valid for enums!");
>
>    typedef /* underlying type */ value_type;
>    static constexpr const value_type min = /* minimum value of enum */
>    static constexpr const value_type max = /* maximum value of enum */
>    static constexpr const value_type ubound = /* maximum value of enum+1.
> Not present (does not compile if queried) if max ==
> numeric_limits<value_type>::max(). (Note: this is the most useful value)*/
>    static constexpr const size_t count = /* Number of enum tags */
>    static constexpr const size_t distinct = /* Number of enum tags with
> distinct values */

Referring to Andrew's comment, I think most of these that I've seen so
far and following can be implemented with N3815 and the relaxed
constexpr rules, but this one might be hard. (I'm not sure how crucial
it is, however; the bound ones are probably most important... also
count, but that one is obviously trivial with N3815.)

>    static constexpr const bool is_contiguious = /* true if enum values are
> contiguous */
>    static constexpr const bool is_regular = is_contiguous && min ==
> value_type(0);
>    static constexpr const bool has_zero = /* true if zero is an enum value */
>    static constexpr const bool has_postive = /* true if at least one enum
> value is positive */
>    static constexpr const bool all_postive = /* true if all enum values are
> positive */

This feels like 'all_nonnegative' is missing...

>    static constexpr const bool has_negative = /* true if at least one enum
> value is negative */
>    static constexpr const bool all_negative = /* true if all enum values are
> negative */
>
> //Utilities to enable foreach, compiler generated
>    class iterator : public std::bidirectional_iterator<E> {
>      public:
>        E operator*();
>        //iterator stuff, operator++ goes to next enum value in operator<()
> order.
>    };
>    class reverse_iterator;
>    struct range {
>
>      iterator begin();
>      iterator end();
>
>      reverse_iterator rbegin();
>      reverse_iterator rend();
>    };
>
>    range<E> loop();
> };
>
> //foreach loop over enum values
> for(auto e : enum_traits<E>::loop()) {
> };

I wonder how hard to implement the iterators are...


I would name 'loop' something like 'values' instead. That said, I would
really love to just be able to say:

enum Enum
{
   ...
};
for (auto e : Enum)
{
   ...
}

....without the extra enum_traits::loop bits. (Actually, if it were/is(?)
possible to specialize std::begin() on an enum type, with the above
and/or N3815 this should already be possible?)


And actually, another thing I would really like to be able to do (and
yes, this *does* happen in real code) is:

for (auto e : std::range(Enum::A, Enum::B, std::range::closed))

(Oh, look; a case for 'inline enum class' :-).)

> Other extensions I'd love to see:
> * enum bitmasks as a real type, easy and expressive to declare

Yes, please!

For API binary stability, there still needs to be a way to specify exact
values. Probably the 'old style' should still be allowed, but it might
greatly simplify matters to allow e.g. 'foo = :5 // equivalent to foo =
1<<5' (assumes ':0' => 0x1). The main thing that's needed is a way to
say that the next value is automatically the highest bit of (2*prev)
rather than (prev+1). Unfortunately I don't have a suggestion for that
syntax.

I could also see allowing 'foo = :2..5' => 0b111100 for ease of
declaring mask values.

> strict
> rules about logical operator comparisons. Only the tags in the enum can use
> binary logical operations with one another.

This already exists, and has since quite some time; see
http://qt-project.org/doc/qt-4.8/qflags.html (dates back even to Qt3 I
think). I'd love to see a std::flags standardized, however. This
shouldn't need language/compiler changes, though (as various parts of
the above might), just an addition to STL.

Actually, I have an implementation of this if anyone is interested?

--
Matthew

--

---
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: Remotion <remotion4d@googlemail.com>
Date: Mon, 13 Jan 2014 11:47:10 -0800 (PST)
Raw View
------=_Part_361_485094.1389642430632
Content-Type: text/plain; charset=ISO-8859-1

IMHO it is possible but much much more complicated as for enums.
This is exactly what I have tried to do here:
https://bitbucket.org/remotion/c-reflection
Right now there are
field_trait to access member variable of the class.
method_traits to access (some) member function of the class.
Constructors and destructor are visible in current implementation.
Also operators and conversion should be visible too.
Static function are not visible, but I think this is OK.
Template functions are not visible and this is one of the problems.
Function that are available by using from base calls are not visible too...

There are also fried_traits to access friend functions and classes.

But there are still a lot of problem with this approach, and right now I am
not sure that it is possible to solve most of them only using 'trait' way.

Namespaces for example are not types so there is no direct way to access
them.
There are also a lot of totally different declaration in namespace.
It is also possible to redeclare (extend) namespace any time at any place.

On Sunday, January 12, 2014 4:41:30 PM UTC+1, inkwizyt...@gmail.com wrote:
>
> Would be possible to create similar functionality for class? If this enum
> approach is possible to implement by every compiler, creating version for
> class should not be impossible.
> This would be more complex because class have private, static, unions,
> fields, base class, sub class and functions, but if we can made interface
> for one thing then creating for rest wouldnt be harder.
>
> On Sunday, January 12, 2014 8:01:12 AM UTC+1, Andrew Tomazos wrote:
>>
>> So, first yes, my co-author Christian has written a reference
>> implementation that contains a superset of the N3815 proposed three
>> property queries.  You will find the link on the bottom of N3815.  This has
>> been forked and extended by Remotion (linked previously in this thread).
>>
>> But before you go diving into that and compiling custom implementation,
>> the three traits are really simple to understand and to mock up by hand
>> with an ordinary compiler:
>>
>> First recall the three property queries are:
>>
>>     enumerator_list_size<E> is the number of enumerators in the
>> enumeration E
>>     enumerator_value<E,I> is a value of type E that is the I'th
>> enumerator in declared order.
>>     enumerator_identifier<E,I> is a string literal with the identifier
>> of the I'th enumerator in declared order.
>>
>> So you can mock them up for experimentation "by hand" without compiler
>> changes as follows:
>>
>> First declare but don't define the three N3815 primaries...
>>
>>     template<typename E> struct enumerator_list_size;
>>     template<typename E, size_t I> struct enumerator_value;
>>     template<typename E, size_t I> struct enumerator_identifier;
>>
>> Then for each enumeration type in your test program, for example...
>>
>>     enum foo
>>     {
>>         bar,
>>         Baz,
>>         Qux = 42,
>>         Quux = 42,
>>     };
>>
>> ...manually define a set of specializations by hand as follows...
>>
>>     template<> struct enumerator_list_size<foo> { static constexpr size_t
>> value = 4; };
>>
>>     template<> struct enumerator_value<foo,0> { static constexpr foo
>> value = bar; };
>>     template<> struct enumerator_value<foo,1> { static constexpr foo
>> value = Baz; };
>>     template<> struct enumerator_value<foo,2> { static constexpr foo
>> value = Qux; };
>>     template<> struct enumerator_value<foo,3> { static constexpr foo
>> value = Quux; };
>>
>>     template<> struct enumerator_identifier<foo,0> { static constexpr
>> char value[4] = u8"bar"; };
>>     template<> struct enumerator_identifier<foo,1> { static constexpr
>> char value[4] = u8"Baz"; };
>>     template<> struct enumerator_identifier<foo,2> { static constexpr
>> char value[4] = u8"Qux"; };
>>     template<> struct enumerator_identifier<foo,3> { static constexpr
>> char value[5] = u8"Quux"; };
>>
>>     constexpr char enumerator_identifier<foo,0>::value[];
>>     constexpr char enumerator_identifier<foo,1>::value[];
>>     constexpr char enumerator_identifier<foo,2>::value[];
>>     constexpr char enumerator_identifier<foo,3>::value[];
>>
>> (The effect of N3815 is that these hand-written specializations will be
>> done automatically for you by the compiler when you use them.)
>>
>> Here is a complete self-contained compiling program with the above
>> integrated together you can copy and paste plus some tests:
>>
>>     #include <cassert>
>>     #include <cstddef>
>>     #include <string.h>
>>
>>     // N3815 primaries
>>     template<typename E> struct enumerator_list_size;
>>     template<typename E, size_t I> struct enumerator_value;
>>     template<typename E, size_t I> struct enumerator_identifier;
>>
>>     // your enumeration
>>     enum foo
>>     {
>>         bar,
>>         Baz,
>>         Qux = 42,
>>         Quux = 42,
>>     };
>>
>>     // define these specializations by hand:
>>     template<> struct enumerator_list_size<foo> { static constexpr size_t
>> value = 4; };
>>
>>     template<> struct enumerator_value<foo,0> { static constexpr foo
>> value = bar; };
>>     template<> struct enumerator_value<foo,1> { static constexpr foo
>> value = Baz; };
>>     template<> struct enumerator_value<foo,2> { static constexpr foo
>> value = Qux; };
>>     template<> struct enumerator_value<foo,3> { static constexpr foo
>> value = Quux; };
>>
>>     template<> struct enumerator_identifier<foo,0> { static constexpr
>> char value[4] = u8"bar"; };
>>     template<> struct enumerator_identifier<foo,1> { static constexpr
>> char value[4] = u8"Baz"; };
>>     template<> struct enumerator_identifier<foo,2> { static constexpr
>> char value[4] = u8"Qux"; };
>>     template<> struct enumerator_identifier<foo,3> { static constexpr
>> char value[5] = u8"Quux"; };
>>
>>     constexpr char enumerator_identifier<foo,0>::value[];
>>     constexpr char enumerator_identifier<foo,1>::value[];
>>     constexpr char enumerator_identifier<foo,2>::value[];
>>     constexpr char enumerator_identifier<foo,3>::value[];
>>
>>     // test they work:
>>     int main()
>>     {
>>         static_assert(enumerator_list_size<foo>::value == 4, "");
>>
>>         assert(strcmp(enumerator_identifier<foo,0>::value, u8"bar") == 0);
>>         assert(strcmp(enumerator_identifier<foo,1>::value, u8"Baz") == 0);
>>         assert(strcmp(enumerator_identifier<foo,2>::value, u8"Qux") == 0);
>>         assert(strcmp(enumerator_identifier<foo,3>::value, u8"Quux") ==
>> 0);
>>
>>         static_assert(enumerator_value<foo,0>::value == bar, "");
>>         static_assert(enumerator_value<foo,1>::value == Baz, "");
>>         static_assert(enumerator_value<foo,2>::value == Qux, "");
>>         static_assert(enumerator_value<foo,3>::value == Quux, "");
>>
>>         constexpr const char* str = enumerator_identifier<foo,0>::value;
>>         static_assert(str[0] == 'b', "");
>>         static_assert(str[1] == 'a', "");
>>         static_assert(str[2] == 'r', "");
>>         static_assert(str[3] == '\0', "");
>>     }
>>
>> Enjoy,
>> Andrew.
>>
>>
>> On Sunday, January 12, 2014 6:16:52 AM UTC+1, fmatth...@gmail.com wrote:
>>>
>>> Sure, is there a working implementation of your proposal? I don't have a
>>> lot of free time so it will be slow, but I can take a look. If so, I might
>>> like to help work on the library features that come after your proposal.
>>>
>>> The list I made is a general sketch of some of the things I think might
>>> be immediatly useful. Many of these I already do manually using crude
>>> interfaces now. It will take some time to come up with a solid library
>>> design with a correctly chosen and designed features.
>>>
>>>
>>>
>>> On Saturday, January 11, 2014 11:39:50 PM UTC-5, Andrew Tomazos wrote:
>>>>
>>>> Could you please review N3815 (
>>>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3815.html) and
>>>> confirm that you can implement your enum_traits and enum_table class as a
>>>> pure library feature on top of the three provided type traits, and that the
>>>> solution would be as efficient as if the compiler did it for you?
>>>>
>>>> If you are unsure or think you have a feature you want that could not
>>>> be implemented on top of the N3815 type traits as an efficient pure library
>>>> feature, could you please point it out?
>>>>
>>>> Our current plan is to standardize N3815 in the Library Fundamentals TS
>>>> as a minmal complete interface that enables library / framework authors to
>>>> provide all this functionality that you want.
>>>>
>>>> From a review of your enum_traits and enum_table class I believe that
>>>> this is indeed the case - that both could all be built efficiently as a
>>>> pure library solution on top of the N3815.  Could you see if you agree.
>>>>
>>>> Thanks,
>>>> Andrew.
>>>>
>>>>
>>>>
>>>> On Saturday, January 11, 2014 7:47:48 AM UTC+1, fmatth...@gmail.comwrote:
>>>>>
>>>>> Enums are one of my favorite tools for efficently labeling
>>>>> collections, but we need to be able to query more information about them.
>>>>>
>>>>> I'd like to suggest some form of enum traits.
>>>>>
>>>>> template <typename E>
>>>>> struct enum_traits<E> {
>>>>>   static_assert(is_enum<E>::value, "Only valid for enums!");
>>>>>
>>>>>   typedef /* underlying type */ value_type;
>>>>>   static constexpr const value_type min = /* minimum value of enum */
>>>>>   static constexpr const value_type max = /* maximum value of enum */
>>>>>   static constexpr const value_type ubound = /* maximum value of
>>>>> enum+1. Not present (does not compile if queried) if max ==
>>>>> numeric_limits<value_type>::max(). (Note: this is the most useful value)*/
>>>>>
>>>>>   static constexpr const size_t count = /* Number of enum tags */
>>>>>   static constexpr const size_t distinct = /* Number of enum tags with
>>>>> distinct values */
>>>>>   static constexpr const bool is_contiguious = /* true if enum values
>>>>> are contiguous */
>>>>>   static constexpr const bool is_regular = is_contiguous && min ==
>>>>> value_type(0);
>>>>>   static constexpr const bool has_zero = /* true if zero is an enum
>>>>> value */
>>>>>   static constexpr const bool has_postive = /* true if at least one
>>>>> enum value is positive */
>>>>>   static constexpr const bool all_postive = /* true if all enum values
>>>>> are positive */
>>>>>   static constexpr const bool has_negative = /* true if at least one
>>>>> enum value is negative */
>>>>>   static constexpr const bool all_negative = /* true if all enum
>>>>> values are negative */
>>>>>
>>>>> //Utilities to enable foreach, compiler generated
>>>>>   class iterator : public std::bidirectional_iterator<E> {
>>>>>     public:
>>>>>       E operator*();
>>>>>       //iterator stuff, operator++ goes to next enum value in
>>>>> operator<() order.
>>>>>   };
>>>>>   class reverse_iterator;
>>>>>   struct range {
>>>>>
>>>>>     iterator begin();
>>>>>     iterator end();
>>>>>
>>>>>     reverse_iterator rbegin();
>>>>>     reverse_iterator rend();
>>>>>   };
>>>>>
>>>>>   range<E> loop();
>>>>> };
>>>>>
>>>>> //foreach loop over enum values
>>>>> for(auto e : enum_traits<E>::loop()) {
>>>>> };
>>>>>
>>>>> //Create tables keyed by enums, standard library component
>>>>> template <typename E, typename T, typename CMP = std::equal_to>
>>>>> class enum_table {
>>>>>   //static asserts if li.size() != enum_traits<E>::distinct;
>>>>>   constexpr enum_table(std::initializer_list<T> li);
>>>>>   constexpr enum_table(const enum_table&) = default;
>>>>>   constexpr enum_table(enum_table&&) = default;
>>>>>   constexpr enum_table& operator=(const enum_table&) = default;
>>>>>   constexpr enum_table& operator=(enum_table&&) = default;
>>>>>
>>>>>   constexpr const T& operator[E tag] const;
>>>>>   constexpr bool lookup(const T& value, E& tag) const;
>>>>>   constexpr bool lookup(T&& value, E& tag) const;
>>>>>   constexpr size_t size() const;
>>>>>
>>>>>   class iterator : std::bidirectional_iterator<std::pair<E, const T&>>
>>>>> {};
>>>>>   class reverse_iterator;
>>>>>
>>>>>   constexpr iterator begin();
>>>>>   constexpr iterator end();
>>>>>   constexpr reverse_iterator rbegin();
>>>>>   constexpr reverse_iterator rend();
>>>>>
>>>>>   constexpr iterator find(E tag);
>>>>>   template <typename Comparable>
>>>>>   constexpr iterator find(Comparable&& c); //lookup using CMP(const
>>>>> T&, C&&) or CMP(const T&, const C&) using perfect forwarding
>>>>>   constexpr iterator find(T&& value); //lookup using CMP()
>>>>> };
>>>>>
>>>>> template <typename E>
>>>>> using enum_strtable = enum_table<E, const char*, [](const char* l,
>>>>> const char* r){ return strcmp(l, r) == 0; }>;
>>>>>
>>>>>
>>>>> //Usage
>>>>> enum Color {
>>>>>   kRed,
>>>>>   kGreen,
>>>>>   kBlue
>>>>> };
>>>>>
>>>>> //Could be place in binary .rodata section.
>>>>> constexpr const enumstr_table<Color> color_tbl = { "Red", "Blue",
>>>>> "Green" };
>>>>>
>>>>> assert(!strcmp(color_tbl[kRed], "Red"));
>>>>> assert(color_tbl.find("Red") != color_tbl.end());
>>>>>
>>>>> I really want this for ubound, and loop(), and runtime string tables
>>>>> but while we're at it, there's a lot of cool stuff we could add.
>>>>> Rationale here:
>>>>>
>>>>> https://groups.google.com/forum/#!searchin/comp.lang.c$2B$2B.moderated/enum/comp.lang.c++.moderated/RpUiU9utY48/N-oUkAo5oIoJ
>>>>>
>>>>> Other extensions I'd love to see:
>>>>> * enum bitmasks as a real type, easy and expressive to declare, strict
>>>>> rules about logical operator comparisons. Only the tags in the enum can use
>>>>> binary logical operations with one another.
>>>>> * concepts in the enum declaration to enforce restrictions
>>>>> (is_contiguous, min == 0, etc..)
>>>>>
>>>>>
>>>>>

--

---
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_361_485094.1389642430632
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">IMHO it is possible but much much more complicated as for =
enums.<br>This is exactly what I have tried to do here:<br>https://bitbucke=
t.org/remotion/c-reflection<br>Right now there are <br>field_trait to acces=
s member variable of the class.<br>method_traits&nbsp;to access (some) memb=
er function of the class.<br>Constructors and destructor are visible in cur=
rent implementation.<br>Also operators and conversion should be visible too=
..<br>Static function are not visible, but I think this is OK.<br>Template f=
unctions are not visible and this is one of the problems.<br>Function that =
are available by using from base calls are not visible too...<br><br>There =
are also fried_traits to access friend functions and classes.<br><br>But th=
ere are still a lot of problem with this approach, and right now I am not s=
ure that it is possible to solve most of them only using 'trait' way.<br><b=
r>Namespaces for example are not types so there is no direct way to access =
them.<br>There are also a lot of totally different declaration in namespace=
..<br>It is also possible to redeclare (extend) namespace any time at any pl=
ace.<br>&nbsp;<br>On Sunday, January 12, 2014 4:41:30 PM UTC+1, inkwizyt...=
@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr">Would be possible to create similar functionality for class? If this en=
um approach is possible to implement by every compiler, creating version fo=
r class should not be impossible.<br>This would be more complex because cla=
ss have private, static, unions, fields, base class, sub class and function=
s, but if we can made interface for one thing then creating for rest wouldn=
t be harder.<br><br>On Sunday, January 12, 2014 8:01:12 AM UTC+1, Andrew To=
mazos 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>S=
o, first yes, my co-author Christian has written a reference implementation=
 that contains a superset of the N3815 proposed three property queries. &nb=
sp;You will find the link on the bottom of N3815. &nbsp;This has been forke=
d and extended by Remotion (linked previously in this thread).</div><div><b=
r></div><div>But before you go diving into that and compiling custom implem=
entation, the three traits are really simple to understand and to mock up b=
y hand with an ordinary compiler:</div><div><br></div><div>First recall the=
 three property queries are:</div><div><br></div><div>&nbsp; &nbsp; <font f=
ace=3D"courier new, monospace">enumerator_list_size&lt;E&gt;</font> is the =
number of enumerators in the enumeration E</div><div>&nbsp; &nbsp; <font fa=
ce=3D"courier new, monospace">enumerator_value&lt;E,I&gt;</font> is a value=
 of type E that is the I'th enumerator in declared order.</div><div>&nbsp; =
&nbsp; <font face=3D"courier new, monospace">enumerator_identifier&lt;E,I&g=
t;</font> is a string literal with the identifier of the I'th enumerator in=
 declared order.</div><div><br></div><div>So you can mock them up for exper=
imentation "by hand" without compiler changes as follows:</div><div><br></d=
iv><div>First declare but don't define the three N3815 primaries...</div><d=
iv><br></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; templ=
ate&lt;typename E&gt; struct enumerator_list_size;</font></div><div><font f=
ace=3D"courier new, monospace">&nbsp; &nbsp; template&lt;typename E, size_t=
 I&gt; struct enumerator_value;</font></div><div><font face=3D"courier new,=
 monospace">&nbsp; &nbsp; template&lt;typename E, size_t I&gt; struct enume=
rator_identifier;</font></div><div><br></div><div>Then for each enumeration=
 type in your test program, for example...</div><div><br></div><div><font f=
ace=3D"courier new, monospace">&nbsp; &nbsp; enum foo</font></div><div><fon=
t face=3D"courier new, monospace">&nbsp; &nbsp; {</font></div><div><font fa=
ce=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; bar,</font></div>=
<div><font face=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; Baz,=
</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; &nbsp=
; &nbsp; Qux =3D 42,</font></div><div><font face=3D"courier new, monospace"=
>&nbsp; &nbsp; &nbsp; &nbsp; Quux =3D 42,</font></div><div><font face=3D"co=
urier new, monospace">&nbsp; &nbsp; };</font></div><div><br></div><div>...m=
anually define a set of specializations by hand as follows...</div><div><br=
></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; template&lt=
;&gt; struct enumerator_list_size&lt;foo&gt; { static constexpr size_t valu=
e =3D 4; };</font></div><div><font face=3D"courier new, monospace"><br></fo=
nt></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; template&=
lt;&gt; struct enumerator_value&lt;foo,0&gt; { static constexpr foo value =
=3D bar; };</font></div><div><font face=3D"courier new, monospace">&nbsp; &=
nbsp; template&lt;&gt; struct enumerator_value&lt;foo,1&gt; { static conste=
xpr foo value =3D Baz; };</font></div><div><font face=3D"courier new, monos=
pace">&nbsp; &nbsp; template&lt;&gt; struct enumerator_value&lt;foo,2&gt; {=
 static constexpr foo value =3D Qux; };</font></div><div><font face=3D"cour=
ier new, monospace">&nbsp; &nbsp; template&lt;&gt; struct enumerator_value&=
lt;foo,3&gt; { static constexpr foo value =3D Quux; };</font></div><div><fo=
nt face=3D"courier new, monospace"><br></font></div><div><font face=3D"cour=
ier new, monospace">&nbsp; &nbsp; template&lt;&gt; struct enumerator_identi=
fier&lt;foo,0&gt; { static constexpr char value[4] =3D u8"bar"; };</font></=
div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; template&lt;&g=
t; struct enumerator_identifier&lt;foo,1&gt; { static constexpr char value[=
4] =3D u8"Baz"; };</font></div><div><font face=3D"courier new, monospace">&=
nbsp; &nbsp; template&lt;&gt; struct enumerator_identifier&lt;foo,2&gt; { s=
tatic constexpr char value[4] =3D u8"Qux"; };</font></div><div><font face=
=3D"courier new, monospace">&nbsp; &nbsp; template&lt;&gt; struct enumerato=
r_identifier&lt;foo,3&gt; { static constexpr char value[5] =3D u8"Quux"; };=
</font></div><div><font face=3D"courier new, monospace"><br></font></div><d=
iv><font face=3D"courier new, monospace">&nbsp; &nbsp; constexpr char enume=
rator_identifier&lt;foo,0&gt;::<wbr>value[];</font></div><div><font face=3D=
"courier new, monospace">&nbsp; &nbsp; constexpr char enumerator_identifier=
&lt;foo,1&gt;::<wbr>value[];</font></div><div><font face=3D"courier new, mo=
nospace">&nbsp; &nbsp; constexpr char enumerator_identifier&lt;foo,2&gt;::<=
wbr>value[];</font></div><div><font face=3D"courier new, monospace">&nbsp; =
&nbsp; constexpr char enumerator_identifier&lt;foo,3&gt;::<wbr>value[];</fo=
nt></div><div><br></div><div>(The effect of N3815 is that these hand-writte=
n specializations will be done automatically for you by the compiler when y=
ou use them.)</div><div><br></div><div>Here is a complete self-contained co=
mpiling program with the above integrated together you can copy and paste p=
lus some tests:</div><div><br></div><div><font face=3D"courier new, monospa=
ce">&nbsp; &nbsp; #include &lt;cassert&gt;</font></div><div><font face=3D"c=
ourier new, monospace">&nbsp; &nbsp; #include &lt;cstddef&gt;</font></div><=
div><font face=3D"courier new, monospace">&nbsp; &nbsp; #include &lt;string=
..h&gt;</font></div><div><font face=3D"courier new, monospace"><br></font></=
div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; // N3815 prima=
ries</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; t=
emplate&lt;typename E&gt; struct enumerator_list_size;</font></div><div><fo=
nt face=3D"courier new, monospace">&nbsp; &nbsp; template&lt;typename E, si=
ze_t I&gt; struct enumerator_value;</font></div><div><font face=3D"courier =
new, monospace">&nbsp; &nbsp; template&lt;typename E, size_t I&gt; struct e=
numerator_identifier;</font></div><div><font face=3D"courier new, monospace=
"><br></font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp;=
 // your enumeration</font></div><div><font face=3D"courier new, monospace"=
>&nbsp; &nbsp; enum foo</font></div><div><font face=3D"courier new, monospa=
ce">&nbsp; &nbsp; {</font></div><div><font face=3D"courier new, monospace">=
&nbsp; &nbsp; &nbsp; &nbsp; bar,</font></div><div><font face=3D"courier new=
, monospace">&nbsp; &nbsp; &nbsp; &nbsp; Baz,</font></div><div><font face=
=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; Qux =3D 42,</font><=
/div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp;=
 Quux =3D 42,</font></div><div><font face=3D"courier new, monospace">&nbsp;=
 &nbsp; };</font></div><div><font face=3D"courier new, monospace"><br></fon=
t></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; // define =
these specializations by hand:</font></div><div><font face=3D"courier new, =
monospace">&nbsp; &nbsp; template&lt;&gt; struct enumerator_list_size&lt;fo=
o&gt; { static constexpr size_t value =3D 4; };</font></div><div><font face=
=3D"courier new, monospace"><br></font></div><div><font face=3D"courier new=
, monospace">&nbsp; &nbsp; template&lt;&gt; struct enumerator_value&lt;foo,=
0&gt; { static constexpr foo value =3D bar; };</font></div><div><font face=
=3D"courier new, monospace">&nbsp; &nbsp; template&lt;&gt; struct enumerato=
r_value&lt;foo,1&gt; { static constexpr foo value =3D Baz; };</font></div><=
div><font face=3D"courier new, monospace">&nbsp; &nbsp; template&lt;&gt; st=
ruct enumerator_value&lt;foo,2&gt; { static constexpr foo value =3D Qux; };=
</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; templ=
ate&lt;&gt; struct enumerator_value&lt;foo,3&gt; { static constexpr foo val=
ue =3D Quux; };</font></div><div><font face=3D"courier new, monospace"><br>=
</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; templ=
ate&lt;&gt; struct enumerator_identifier&lt;foo,0&gt; { static constexpr ch=
ar value[4] =3D u8"bar"; };</font></div><div><font face=3D"courier new, mon=
ospace">&nbsp; &nbsp; template&lt;&gt; struct enumerator_identifier&lt;foo,=
1&gt; { static constexpr char value[4] =3D u8"Baz"; };</font></div><div><fo=
nt face=3D"courier new, monospace">&nbsp; &nbsp; template&lt;&gt; struct en=
umerator_identifier&lt;foo,2&gt; { static constexpr char value[4] =3D u8"Qu=
x"; };</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp;=
 template&lt;&gt; struct enumerator_identifier&lt;foo,3&gt; { static conste=
xpr char value[5] =3D u8"Quux"; };</font></div><div><font face=3D"courier n=
ew, monospace"><br></font></div><div><font face=3D"courier new, monospace">=
&nbsp; &nbsp; constexpr char enumerator_identifier&lt;foo,0&gt;::<wbr>value=
[];</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; co=
nstexpr char enumerator_identifier&lt;foo,1&gt;::<wbr>value[];</font></div>=
<div><font face=3D"courier new, monospace">&nbsp; &nbsp; constexpr char enu=
merator_identifier&lt;foo,2&gt;::<wbr>value[];</font></div><div><font face=
=3D"courier new, monospace">&nbsp; &nbsp; constexpr char enumerator_identif=
ier&lt;foo,3&gt;::<wbr>value[];</font></div><div><font face=3D"courier new,=
 monospace"><br></font></div><div><font face=3D"courier new, monospace">&nb=
sp; &nbsp; // test they work:</font></div><div><font face=3D"courier new, m=
onospace">&nbsp; &nbsp; int main()</font></div><div><font face=3D"courier n=
ew, monospace">&nbsp; &nbsp; {</font></div><div><font face=3D"courier new, =
monospace">&nbsp; &nbsp; &nbsp; &nbsp; static_assert(enumerator_list_<wbr>s=
ize&lt;foo&gt;::value =3D=3D 4, "");</font></div><div><font face=3D"courier=
 new, monospace"><br></font></div><div><font face=3D"courier new, monospace=
">&nbsp; &nbsp; &nbsp; &nbsp; assert(strcmp(enumerator_<wbr>identifier&lt;f=
oo,0&gt;::value, u8"bar") =3D=3D 0);</font></div><div><font face=3D"courier=
 new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; assert(strcmp(enumerator_<wbr>=
identifier&lt;foo,1&gt;::value, u8"Baz") =3D=3D 0);</font></div><div><font =
face=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; assert(strcmp(e=
numerator_<wbr>identifier&lt;foo,2&gt;::value, u8"Qux") =3D=3D 0);</font></=
div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; =
assert(strcmp(enumerator_<wbr>identifier&lt;foo,3&gt;::value, u8"Quux") =3D=
=3D 0);</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp=
; &nbsp; &nbsp;</font></div><div><font face=3D"courier new, monospace">&nbs=
p; &nbsp; &nbsp; &nbsp; static_assert(enumerator_<wbr>value&lt;foo,0&gt;::v=
alue =3D=3D bar, "");</font></div><div><font face=3D"courier new, monospace=
">&nbsp; &nbsp; &nbsp; &nbsp; static_assert(enumerator_<wbr>value&lt;foo,1&=
gt;::value =3D=3D Baz, "");</font></div><div><font face=3D"courier new, mon=
ospace">&nbsp; &nbsp; &nbsp; &nbsp; static_assert(enumerator_<wbr>value&lt;=
foo,2&gt;::value =3D=3D Qux, "");</font></div><div><font face=3D"courier ne=
w, monospace">&nbsp; &nbsp; &nbsp; &nbsp; static_assert(enumerator_<wbr>val=
ue&lt;foo,3&gt;::value =3D=3D Quux, "");</font></div><div><font face=3D"cou=
rier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp;</font></div><div><font fac=
e=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; constexpr const ch=
ar* str =3D enumerator_identifier&lt;foo,0&gt;::<wbr>value;</font></div><di=
v><font face=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; static_=
assert(str[0] =3D=3D 'b', "");</font></div><div><font face=3D"courier new, =
monospace">&nbsp; &nbsp; &nbsp; &nbsp; static_assert(str[1] =3D=3D 'a', "")=
;</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; &nbs=
p; &nbsp; static_assert(str[2] =3D=3D 'r', "");</font></div><div><font face=
=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; static_assert(str[3=
] =3D=3D '\0', "");</font></div><div><font face=3D"courier new, monospace">=
&nbsp; &nbsp; }</font></div><div><br></div><div>Enjoy,</div><div>Andrew.</d=
iv><div><br></div><br>On Sunday, January 12, 2014 6:16:52 AM UTC+1, <a>fmat=
th...@gmail.com</a> 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">Sure, is there a working implementation of your proposal? I don't =
have a lot of free time so it will be slow, but I can take a look. If so, I=
 might like to help work on the library features that come after your propo=
sal.&nbsp;<div><br></div><div>The list I made is a general sketch of some o=
f the things I think might be immediatly useful. Many of these I already do=
 manually using crude interfaces now. It will take some time to come up wit=
h a solid library design with a correctly chosen and designed features.</di=
v><div><br></div><div><br><br>On Saturday, January 11, 2014 11:39:50 PM UTC=
-5, Andrew Tomazos 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">Could you please review N3815 (<a href=3D"http://www.open-std.org/=
jtc1/sc22/wg21/docs/papers/2013/n3815.html" target=3D"_blank" onmousedown=
=3D"this.href=3D'http://www.google.com/url?q\75http%3A%2F%2Fwww.open-std.or=
g%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2013%2Fn3815.html\46sa\75D\46sntz\=
0751\46usg\75AFQjCNHwe7liqoidkU5rvKFSWklGuTd4gw';return true;" onclick=3D"t=
his.href=3D'http://www.google.com/url?q\75http%3A%2F%2Fwww.open-std.org%2Fj=
tc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2013%2Fn3815.html\46sa\75D\46sntz\0751\=
46usg\75AFQjCNHwe7liqoidkU5rvKFSWklGuTd4gw';return true;">http://www.open-s=
td.org/jtc1/<wbr>sc22/wg21/docs/papers/2013/<wbr>n3815.html</a>)&nbsp;and c=
onfirm that you can implement your enum_traits and enum_table class as a pu=
re library feature on top of the three provided type traits, and that the s=
olution would be as efficient as if the compiler did it for you?<div><br></=
div><div>If you are unsure or think you have a feature you want that could =
not be implemented on top of the N3815 type traits as an efficient pure lib=
rary feature, could you please point it out?</div><div><br></div><div>Our c=
urrent plan is to standardize N3815 in the Library Fundamentals TS as a min=
mal complete interface that enables library / framework authors to provide =
all this functionality that you want.</div><div><br></div><div>From a revie=
w of your enum_traits and enum_table class I believe that this is indeed th=
e case - that both could all be built efficiently as a pure library solutio=
n on top of the N3815. &nbsp;Could you see if you agree.<br><br>Thanks,</di=
v><div>Andrew.</div><div><br><br><br>On Saturday, January 11, 2014 7:47:48 =
AM UTC+1, <a>fmatth...@gmail.com</a> wrote:<blockquote class=3D"gmail_quote=
" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-le=
ft:1ex"><div dir=3D"ltr">Enums are one of my favorite tools for efficently =
labeling collections, but we need to be able to query more information abou=
t them.<div><br></div><div>I'd like to suggest some form of enum traits.&nb=
sp;</div><div><br></div><div>template &lt;typename E&gt;</div><div>struct e=
num_traits&lt;E&gt; {</div><div>&nbsp; static_assert(is_enum&lt;E&gt;::<wbr=
>value, "Only valid for enums!");</div><div>&nbsp;&nbsp;</div><div>&nbsp; t=
ypedef /* underlying type */ value_type;</div><div>&nbsp; static constexpr =
const value_type min =3D /* minimum value of enum */</div><div>&nbsp; stati=
c constexpr const value_type max =3D /* maximum value of enum */</div><div>=
&nbsp; static constexpr const value_type ubound =3D /* maximum value of enu=
m+1. Not present (does not compile if queried) if max =3D=3D numeric_limits=
&lt;value_type&gt;::<wbr>max(). (Note: this is the most useful value)*/</di=
v><div><br></div><div>&nbsp; static constexpr const size_t count =3D /* Num=
ber of enum tags */</div><div>&nbsp; static constexpr const size_t distinct=
 =3D /* Number of enum tags with distinct values */&nbsp;</div><div>&nbsp; =
static constexpr const bool is_contiguious =3D /* true if enum values are c=
ontiguous */</div><div>&nbsp; static constexpr const bool is_regular =3D is=
_contiguous &amp;&amp; min =3D=3D value_type(0);</div><div>&nbsp; static co=
nstexpr const bool has_zero =3D /* true if zero is an enum value */</div><d=
iv>&nbsp; static constexpr const bool has_postive =3D /* true if at least o=
ne enum value is positive */</div><div>&nbsp; static constexpr const bool a=
ll_postive =3D /* true if all enum values are positive */</div><div>&nbsp; =
static constexpr const bool has_negative =3D /* true if at least one enum v=
alue is negative */</div><div>&nbsp; static constexpr const bool all_negati=
ve =3D /* true if all enum values are negative */</div><div><br></div><div>=
//Utilities to enable foreach, compiler generated</div><div>&nbsp; class it=
erator : public std::bidirectional_iterator&lt;E&gt; {</div><div>&nbsp; &nb=
sp; public:</div><div>&nbsp; &nbsp; &nbsp; E operator*();</div><div>&nbsp; =
&nbsp; &nbsp; //iterator stuff, operator++ goes to next enum value in opera=
tor&lt;() order.</div><div>&nbsp; };</div><div>&nbsp; class reverse_iterato=
r;</div><div>&nbsp; struct range {</div><div><br></div><div>&nbsp; &nbsp; i=
terator begin();</div><div>&nbsp; &nbsp; iterator end();</div><div><br></di=
v><div>&nbsp; &nbsp; reverse_iterator rbegin();</div><div>&nbsp; &nbsp; rev=
erse_iterator rend();<br>&nbsp; };</div><div><br></div><div>&nbsp; range&lt=
;E&gt; loop();</div><div>};</div><div><br></div><div>//foreach loop over en=
um values</div><div>for(auto e : enum_traits&lt;E&gt;::loop()) {<br>};</div=
><div><br></div><div>//Create tables keyed by enums, standard library compo=
nent</div><div>template &lt;typename E, typename T, typename CMP =3D std::e=
qual_to&gt;</div><div>class enum_table {</div><div>&nbsp; //static asserts =
if li.size() !=3D enum_traits&lt;E&gt;::distinct;</div><div>&nbsp; constexp=
r enum_table(std::initializer_<wbr>list&lt;T&gt; li);</div><div>&nbsp; cons=
texpr enum_table(const enum_table&amp;) =3D default;</div><div>&nbsp; const=
expr enum_table(enum_table&amp;&amp;) =3D default;</div><div><div>&nbsp; co=
nstexpr enum_table&amp; operator=3D(const enum_table&amp;) =3D default;</di=
v><div>&nbsp; constexpr enum_table&amp; operator=3D(enum_table&amp;&amp;) =
=3D default;</div></div><div><br></div><div>&nbsp; constexpr const T&amp; o=
perator[E tag] const;</div><div>&nbsp; constexpr bool lookup(const T&amp; v=
alue, E&amp; tag) const;</div><div>&nbsp; constexpr bool lookup(T&amp;&amp;=
 value, E&amp; tag) const;</div><div>&nbsp; constexpr size_t size() const;<=
/div><div><br></div><div>&nbsp; class iterator : std::bidirectional_iterato=
r&lt;<wbr>std::pair&lt;E, const T&amp;&gt;&gt; {};</div><div>&nbsp; class r=
everse_iterator;</div><div>&nbsp;&nbsp;</div><div>&nbsp; constexpr iterator=
 begin();</div><div>&nbsp; constexpr iterator end();</div><div><div>&nbsp; =
constexpr reverse_iterator rbegin();</div><div>&nbsp; constexpr reverse_ite=
rator rend();</div><div><br></div><div>&nbsp; constexpr iterator find(E tag=
);</div><div>&nbsp; template &lt;typename Comparable&gt;</div><div>&nbsp; c=
onstexpr iterator find(Comparable&amp;&amp; c); //lookup using CMP(const T&=
amp;, C&amp;&amp;) or CMP(const T&amp;, const C&amp;) using perfect forward=
ing</div><div>&nbsp; constexpr iterator find(T&amp;&amp; value); //lookup u=
sing CMP()</div>};</div><div><br></div><div>template &lt;typename E&gt;</di=
v><div>using enum_strtable =3D enum_table&lt;E, const char*, [](const char*=
 l, const char* r){ return strcmp(l, r) =3D=3D 0; }&gt;;</div><div><br></di=
v><div><br></div><div>//Usage</div><div>enum Color {<br>&nbsp; kRed,</div><=
div>&nbsp; kGreen,</div><div>&nbsp; kBlue</div><div>};</div><div><br></div>=
<div>//Could be place in binary .rodata section.</div><div>constexpr const =
enumstr_table&lt;Color&gt; color_tbl =3D { "Red", "Blue", "Green" };</div><=
div><br></div><div>assert(!strcmp(color_tbl[kRed]<wbr>, "Red"));</div><div>=
assert(color_tbl.find("Red") !=3D color_tbl.end());</div><div><br></div><di=
v>I really want this for ubound, and loop(), and runtime string tables but =
while we're at it, there's a lot of cool stuff we could add.</div><div>Rati=
onale here:</div><div><a href=3D"https://groups.google.com/forum/#!searchin=
/comp.lang.c$2B$2B.moderated/enum/comp.lang.c++.moderated/RpUiU9utY48/N-oUk=
Ao5oIoJ" target=3D"_blank" onmousedown=3D"this.href=3D'https://groups.googl=
e.com/forum/#!searchin/comp.lang.c$2B$2B.moderated/enum/comp.lang.c++.moder=
ated/RpUiU9utY48/N-oUkAo5oIoJ';return true;" onclick=3D"this.href=3D'https:=
//groups.google.com/forum/#!searchin/comp.lang.c$2B$2B.moderated/enum/comp.=
lang.c++.moderated/RpUiU9utY48/N-oUkAo5oIoJ';return true;">https://groups.g=
oogle.com/<wbr>forum/#!searchin/comp.lang.c$<wbr>2B$2B.moderated/enum/comp.=
<wbr>lang.c++.moderated/<wbr>RpUiU9utY48/N-oUkAo5oIoJ</a><br></div><div><br=
></div><div>Other extensions I'd love to see:</div><div>* enum bitmasks as =
a real type, easy and expressive to declare, strict rules about logical ope=
rator comparisons. Only the tags in the enum can use binary logical operati=
ons with one another.</div><div>* concepts in the enum declaration to enfor=
ce restrictions (is_contiguous, min =3D=3D 0, etc..)</div><div><br></div><d=
iv><br></div></div></blockquote></div></div></blockquote></div></div></bloc=
kquote></div></blockquote></div></blockquote></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_361_485094.1389642430632--

.


Author: inkwizytoryankes@gmail.com
Date: Mon, 13 Jan 2014 13:04:39 -0800 (PST)
Raw View
------=_Part_852_16627994.1389647079673
Content-Type: text/plain; charset=ISO-8859-1

Mouse have "variadic" size :) Its not uncommon to have enum that have more
than 200 values (e.g. keyboard mappings), this will require lot more from
compiler reflection than trivial struct like `struct Foo{};`.
Some previous proposition used `tuple` to store information. That cant
handle easily lot of data.

I dont think that we need complex reflection that will handle all possible
user case and properties of class. We could start form small subset that
isnt more complex than enum case. And after is is implements by major
compilers we could expand it further. I think first goal should be
functionality that allow automatic serialization of POD type to text format
like JSON.

Something like Remotion proposition is close to that goal.

On Monday, January 13, 2014 2:08:45 AM UTC+1, Andrew Tomazos wrote:
>
> On Sunday, January 12, 2014 4:41:30 PM UTC+1, inkwizyt...@gmail.com wrote:
>>
>> Would be possible to create similar functionality for class? If this enum
>> approach is possible to implement by every compiler, creating version for
>> class should not be impossible.
>>
>
> If I can fit a mouse in my pocket, I must be able to fit an elephant too,
> because they are both animals.  Also known as a hasty generalization.
>
> Enumeration types are just a multiset of named integral constants where
> the names are always identifiers.  We will support complete efficient
> reflection of enumeration types with the three N3815 type traits as a tiny
> extension to that existing library.  The additional standard wording to
> specify them was only 50 words.
>
> This would be more complex because class have private, static, unions,
>> fields, base class, sub class and functions, but if we can made interface
>> for one thing then creating for rest wouldnt be harder.
>>
>
> You've massively understated the difference in complexity between
> enumeration types and class types.
>
> Enumeration types are specified by 4 pages in the standard (7.2)
>
> Class types are specified by 69 pages (clauses 9, 10, 11, 12) even if you
> handwaive the fact that they can contain member templates (an additional 74
> pages).
>
> Having said that the reference implementation of N3815 does also include a
> bunch of additional intrinsics to perform some forms of class type
> reflection, but nothing we are proposing for standardization.
>
> On top of the sheer difficulty of designing a complete standard schema for
> class types that the compiler should expose, we also have the problem that
> the C++ language isn't there yet in being able to handle the complexity of
> such a schema at compile-time.  At compile-time you have to model the
> schema using some combination of literal types, constant expressions,
> constexpr functions and template-metaprogramming.  The type traits approach
> chokes on the complexity at this point.  For a sane approach we really need
> basic primitives like dynamic memory and polymorphic types like the
> compiler itself uses internally to describe the model, but these are not
> yet available during translation in C++.
>
> I do have some rough designs for a larger extensible C++ reflection
> framework that would include class types.  It works with opaque handles and
> a couple of new core language operators called reflect and reify, but it
> would be something for C++17 at the earliest if it works out at all.
>
>

--

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

------=_Part_852_16627994.1389647079673
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Mouse have "variadic" size :) Its not uncommon to have enu=
m that have=20
more than 200 values (e.g. keyboard mappings), this will require lot=20
more from compiler reflection than trivial struct like `struct Foo{};`.<br>=
Some previous proposition used `tuple` to store information. That cant hand=
le easily lot of data.<br><br>I
 dont think that we need complex reflection that will handle all=20
possible user case and properties of class. We could start form small=20
subset that isnt more complex than enum case. And after is is implements
 by major compilers we could expand it further. I think first goal should b=
e functionality that allow automatic serialization of POD type to text form=
at like JSON.<br><br>Something like Remotion proposition is close to that g=
oal.<br><br>On Monday, January 13, 2014 2:08:45 AM UTC+1, Andrew Tomazos wr=
ote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex=
;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>On S=
unday, January 12, 2014 4:41:30 PM UTC+1, <a>inkwizyt...@gmail.com</a> wrot=
e:<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;borde=
r-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid=
;padding-left:1ex"><div dir=3D"ltr">Would be possible to create similar fun=
ctionality for class? If this enum approach is possible to implement by eve=
ry compiler, creating version for class should not be impossible.<br></div>=
</blockquote><div>&nbsp;</div></div>If I can fit a mouse in my pocket, I mu=
st be able to fit an elephant too, because they are both animals. &nbsp;Als=
o known as a hasty generalization.<div><br></div><div>Enumeration types are=
 just a multiset of named integral constants where the names are always ide=
ntifiers. &nbsp;We will support complete efficient reflection of enumeratio=
n types with the three N3815 type traits as a tiny extension to that existi=
ng library. &nbsp;The additional standard wording to specify them was only =
50 words.</div><div><br></div><div><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(20=
4,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr">This =
would be more complex because class have private, static, unions, fields, b=
ase class, sub class and functions, but if we can made interface for one th=
ing then creating for rest wouldnt be harder.</div></blockquote><div><br></=
div><div>You've massively understated the difference in complexity between =
enumeration types and class types.</div><div><br></div></div><div>Enumerati=
on types are specified by 4 pages in the standard (7.2)</div><div><br></div=
><div>Class types are specified by 69 pages (clauses 9, 10, 11, 12) even if=
 you handwaive the fact that they can contain member templates (an addition=
al 74 pages).</div><div><br></div><div>Having said that the reference imple=
mentation of N3815 does also include a bunch of additional intrinsics to pe=
rform some forms of class type reflection, but nothing we are proposing for=
 standardization.</div><div><br></div><div>On top of the sheer difficulty o=
f designing a complete standard schema for class types that the compiler sh=
ould expose, we also have the problem that the C++ language isn't there yet=
 in being able to handle the complexity of such a schema at compile-time. &=
nbsp;At compile-time you have to model the schema using some combination of=
 literal types, constant expressions, constexpr functions and template-meta=
programming. &nbsp;The type traits approach chokes on the complexity at thi=
s point. &nbsp;For a sane approach we really need basic primitives like dyn=
amic memory and polymorphic types like the compiler itself uses internally =
to describe the model, but these are not yet available during translation i=
n C++.</div><div><br></div><div>I do have some rough designs for a larger e=
xtensible C++ reflection framework that would include class types. &nbsp;It=
 works with opaque handles and a couple of new core language operators call=
ed reflect and reify, but it would be something for C++17 at the earliest i=
f it works out at all.</div><div><br></div></div></blockquote></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_852_16627994.1389647079673--

.


Author: fmatthew5876@gmail.com
Date: Mon, 13 Jan 2014 18:52:37 -0800 (PST)
Raw View
------=_Part_1496_20823269.1389667957344
Content-Type: text/plain; charset=ISO-8859-1



On Monday, January 13, 2014 1:13:37 PM UTC-5, Matthew Woehlke wrote:
>
> On 2014-01-11 01:47, fmatth...@gmail.com <javascript:> wrote:
> > Enums are one of my favorite tools for efficently labeling collections,
> but
> > we need to be able to query more information about them.
> >
> > I'd like to suggest some form of enum traits.
> >
> > template <typename E>
> > struct enum_traits<E> {
> >    static_assert(is_enum<E>::value, "Only valid for enums!");
> >
> >    typedef /* underlying type */ value_type;
> >    static constexpr const value_type min = /* minimum value of enum */
> >    static constexpr const value_type max = /* maximum value of enum */
> >    static constexpr const value_type ubound = /* maximum value of
> enum+1.
> > Not present (does not compile if queried) if max ==
> > numeric_limits<value_type>::max(). (Note: this is the most useful
> value)*/
> >    static constexpr const size_t count = /* Number of enum tags */
> >    static constexpr const size_t distinct = /* Number of enum tags with
> > distinct values */
>
> Referring to Andrew's comment, I think most of these that I've seen so
> far and following can be implemented with N3815 and the relaxed
> constexpr rules, but this one might be hard. (I'm not sure how crucial
> it is, however; the bound ones are probably most important... also
> count, but that one is obviously trivial with N3815.)
>

For iteration, you'd want to only iterate over the distinct values. That
could require some trickery to get right, which could be optimized away if
distinct == true. I need to sit down and think about implementations though.

>
> >    static constexpr const bool is_contiguious = /* true if enum values
> are
> > contiguous */
> >    static constexpr const bool is_regular = is_contiguous && min ==
> > value_type(0);
> >    static constexpr const bool has_zero = /* true if zero is an enum
> value */
> >    static constexpr const bool has_postive = /* true if at least one
> enum
> > value is positive */
> >    static constexpr const bool all_postive = /* true if all enum values
> are
> > positive */
>
> This feels like 'all_nonnegative' is missing...
>

Yes of course, this was just a general idea of what could be done. I
actually don't know if all_positive and friends are actually useful. I
certainly don't need them for anything.

>
> >    static constexpr const bool has_negative = /* true if at least one
> enum
> > value is negative */
> >    static constexpr const bool all_negative = /* true if all enum values
> are
> > negative */
> >
> > //Utilities to enable foreach, compiler generated
> >    class iterator : public std::bidirectional_iterator<E> {
> >      public:
> >        E operator*();
> >        //iterator stuff, operator++ goes to next enum value in
> operator<()
> > order.
> >    };
> >    class reverse_iterator;
> >    struct range {
> >
> >      iterator begin();
> >      iterator end();
> >
> >      reverse_iterator rbegin();
> >      reverse_iterator rend();
> >    };
> >
> >    range<E> loop();
> > };
> >
> > //foreach loop over enum values
> > for(auto e : enum_traits<E>::loop()) {
> > };
>
> I wonder how hard to implement the iterators are...
>
> Second to having enum_strtable, this feature is crucial to me. I use enums
a lot in C++ and iterating over the values is something I've needed to do
many times. right now its just the simple for loop with a cast. It would be
nice to have this feature provided by the standard library and be nice and
type safe.

>
> I would name 'loop' something like 'values' instead. That said, I would
> really love to just be able to say:
>
> enum Enum
> {
>    ...
> };
> for (auto e : Enum)
> {
>    ...
> }
>

Enum is a type so this is inventing a whole new syntax (which I am not
terribly opposed to, less typing is always good). I think its more sensible
to just create a temporary object and iterate over that, letting the
compiler optimize away the temporary object and just give you a loop.

Something like this:

template <typename E>
class enum_range {};

for(auto e: enum_range<Enum>()) { }

if enum_traits<Enum>::is_contiguous == true, the goal is that this should
optimize down to a simple integer for loop. If is_contiguous == false, then
the implementation could use a simple lookup table:

enum Bar {
A = 1,
B = 5,
C = 8,
D = 5
};

for(auto e: enum_range<Bar>()) {}

constexpr int table[] = { 1, 5, 8 }; //Only 3 elements, since D == B
for(int i = 0; i < sizeof(table)/sizeof(*table); ++i) {
  Bar b = Bar(table[i]);
}



>
> ...without the extra enum_traits::loop bits. (Actually, if it were/is(?)
> possible to specialize std::begin() on an enum type, with the above
> and/or N3815 this should already be possible?)
>

I'm not sure having begin()/end() on the enum type itself actually makes
sense. An enum object is just one tagged object, not the whole collection

Color color = kRed;
for(auto c: color) { /*???*/ }

>
>
> And actually, another thing I would really like to be able to do (and
> yes, this *does* happen in real code) is:
>
> for (auto e : std::range(Enum::A, Enum::B, std::range::closed))
>
I haven't studied the ranges proposal, but from what I think this is
supposed to do it looks like a nice feature.


>
> (Oh, look; a case for 'inline enum class' :-).)
>
> > Other extensions I'd love to see:
> > * enum bitmasks as a real type, easy and expressive to declare
>
> Yes, please!
>
> For API binary stability, there still needs to be a way to specify exact
> values. Probably the 'old style' should still be allowed, but it might
> greatly simplify matters to allow e.g. 'foo = :5 // equivalent to foo =
> 1<<5' (assumes ':0' => 0x1). The main thing that's needed is a way to
> say that the next value is automatically the highest bit of (2*prev)
> rather than (prev+1). Unfortunately I don't have a suggestion for that
> syntax.
>
> I could also see allowing 'foo = :2..5' => 0b111100 for ease of
> declaring mask values.
>

I'm thinking more something like this:
enum Flags : some_syntax_that_makes_this_a_bitmask_enum {
  f1, //Defaults to 1 << 1
  f2, // 1 << 2
  f3, // 1 << 3
  f4, // 1 << 4
  f5 = 8, //1 << 8
  f6 = 42, //1 << 42, also promotes the unspecified underlying type to at
least 64 bit integer
  f8 = 129, // 1 << 129, promotes type to std::bitset? Or maybe we
static_assert here?
};


>
> > strict
> > rules about logical operator comparisons. Only the tags in the enum can
> use
> > binary logical operations with one another.
>
> This already exists, and has since quite some time; see
> http://qt-project.org/doc/qt-4.8/qflags.html (dates back even to Qt3 I
> think). I'd love to see a std::flags standardized, however. This
> shouldn't need language/compiler changes, though (as various parts of
> the above might), just an addition to STL.
>
> Actually, I have an implementation of this if anyone is interested?
>

I'd be interested to know if you changed your design from qt's qflags and
if so why and how that worked out for you.


>
> --
> Matthew
>
>

--

---
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_1496_20823269.1389667957344
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>On Monday, January 13, 2014 1:13:37 PM UTC-5, Matt=
hew Woehlke wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On 2014-01-1=
1 01:47, <a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D=
"HO5p37rXGswJ" onmousedown=3D"this.href=3D'javascript:';return true;" oncli=
ck=3D"this.href=3D'javascript:';return true;">fmatth...@gmail.com</a> wrote=
:
<br>&gt; Enums are one of my favorite tools for efficently labeling collect=
ions, but
<br>&gt; we need to be able to query more information about them.
<br>&gt;
<br>&gt; I'd like to suggest some form of enum traits.
<br>&gt;
<br>&gt; template &lt;typename E&gt;
<br>&gt; struct enum_traits&lt;E&gt; {
<br>&gt; &nbsp; &nbsp;static_assert(is_enum&lt;E&gt;::<wbr>value, "Only val=
id for enums!");
<br>&gt;
<br>&gt; &nbsp; &nbsp;typedef /* underlying type */ value_type;
<br>&gt; &nbsp; &nbsp;static constexpr const value_type min =3D /* minimum =
value of enum */
<br>&gt; &nbsp; &nbsp;static constexpr const value_type max =3D /* maximum =
value of enum */
<br>&gt; &nbsp; &nbsp;static constexpr const value_type ubound =3D /* maxim=
um value of enum+1.
<br>&gt; Not present (does not compile if queried) if max =3D=3D
<br>&gt; numeric_limits&lt;value_type&gt;::<wbr>max(). (Note: this is the m=
ost useful value)*/
<br>&gt; &nbsp; &nbsp;static constexpr const size_t count =3D /* Number of =
enum tags */
<br>&gt; &nbsp; &nbsp;static constexpr const size_t distinct =3D /* Number =
of enum tags with
<br>&gt; distinct values */
<br>
<br>Referring to Andrew's comment, I think most of these that I've seen so=
=20
<br>far and following can be implemented with N3815 and the relaxed=20
<br>constexpr rules, but this one might be hard. (I'm not sure how crucial=
=20
<br>it is, however; the bound ones are probably most important... also=20
<br>count, but that one is obviously trivial with N3815.)
<br></blockquote><div><br></div><div>For iteration, you'd want to only iter=
ate over the distinct values. That could require some trickery to get right=
, which could be optimized away if distinct =3D=3D true. I need to sit down=
 and think about implementations though.</div><blockquote class=3D"gmail_qu=
ote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padd=
ing-left: 1ex;">
<br>&gt; &nbsp; &nbsp;static constexpr const bool is_contiguious =3D /* tru=
e if enum values are
<br>&gt; contiguous */
<br>&gt; &nbsp; &nbsp;static constexpr const bool is_regular =3D is_contigu=
ous &amp;&amp; min =3D=3D
<br>&gt; value_type(0);
<br>&gt; &nbsp; &nbsp;static constexpr const bool has_zero =3D /* true if z=
ero is an enum value */
<br>&gt; &nbsp; &nbsp;static constexpr const bool has_postive =3D /* true i=
f at least one enum
<br>&gt; value is positive */
<br>&gt; &nbsp; &nbsp;static constexpr const bool all_postive =3D /* true i=
f all enum values are
<br>&gt; positive */
<br>
<br>This feels like 'all_nonnegative' is missing...
<br></blockquote><div><br></div><div>Yes of course, this was just a general=
 idea of what could be done. I actually don't know if all_positive and frie=
nds are actually useful. I certainly don't need them for anything.</div><bl=
ockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border=
-left: 1px #ccc solid;padding-left: 1ex;">
<br>&gt; &nbsp; &nbsp;static constexpr const bool has_negative =3D /* true =
if at least one enum
<br>&gt; value is negative */
<br>&gt; &nbsp; &nbsp;static constexpr const bool all_negative =3D /* true =
if all enum values are
<br>&gt; negative */
<br>&gt;
<br>&gt; //Utilities to enable foreach, compiler generated
<br>&gt; &nbsp; &nbsp;class iterator : public std::bidirectional_iterator&l=
t;E&gt; {
<br>&gt; &nbsp; &nbsp; &nbsp;public:
<br>&gt; &nbsp; &nbsp; &nbsp; &nbsp;E operator*();
<br>&gt; &nbsp; &nbsp; &nbsp; &nbsp;//iterator stuff, operator++ goes to ne=
xt enum value in operator&lt;()
<br>&gt; order.
<br>&gt; &nbsp; &nbsp;};
<br>&gt; &nbsp; &nbsp;class reverse_iterator;
<br>&gt; &nbsp; &nbsp;struct range {
<br>&gt;
<br>&gt; &nbsp; &nbsp; &nbsp;iterator begin();
<br>&gt; &nbsp; &nbsp; &nbsp;iterator end();
<br>&gt;
<br>&gt; &nbsp; &nbsp; &nbsp;reverse_iterator rbegin();
<br>&gt; &nbsp; &nbsp; &nbsp;reverse_iterator rend();
<br>&gt; &nbsp; &nbsp;};
<br>&gt;
<br>&gt; &nbsp; &nbsp;range&lt;E&gt; loop();
<br>&gt; };
<br>&gt;
<br>&gt; //foreach loop over enum values
<br>&gt; for(auto e : enum_traits&lt;E&gt;::loop()) {
<br>&gt; };
<br>
<br>I wonder how hard to implement the iterators are...
<br>
<br></blockquote><div>Second to having enum_strtable, this feature is cruci=
al to me. I use enums a lot in C++ and iterating over the values is somethi=
ng I've needed to do many times. right now its just the simple for loop wit=
h a cast. It would be nice to have this feature provided by the standard li=
brary and be nice and type safe.</div><blockquote class=3D"gmail_quote" sty=
le=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left=
: 1ex;">
<br>I would name 'loop' something like 'values' instead. That said, I would=
=20
<br>really love to just be able to say:
<br>
<br>enum Enum
<br>{
<br>&nbsp; &nbsp;...
<br>};
<br>for (auto e : Enum)
<br>{
<br>&nbsp; &nbsp;...
<br>}
<br></blockquote><div><br></div><div>Enum is a type so this is inventing a =
whole new syntax (which I am not terribly opposed to, less typing is always=
 good). I think its more sensible to just create a temporary object and ite=
rate over that, letting the compiler optimize away the temporary object and=
 just give you a loop.</div><div><span style=3D"font-size: 13px;"><br></spa=
n></div><div><span style=3D"font-size: 13px;">Something like this:</span></=
div><div><span style=3D"font-size: 13px;"><br></span></div><div><span style=
=3D"font-size: 13px;">template &lt;typename E&gt;</span></div><div><span st=
yle=3D"font-size: 13px;">class enum_range {};</span></div><div><span style=
=3D"font-size: 13px;"><br></span></div><div><span style=3D"font-size: 13px;=
">for(auto e: enum_range&lt;Enum&gt;()) { }</span></div><div><span style=3D=
"font-size: 13px;"><br></span></div><div><span style=3D"font-size: 13px;">i=
f enum_traits&lt;Enum&gt;::is_contiguous =3D=3D true, the goal is that this=
 should optimize down to a simple integer for loop. If is_contiguous =3D=3D=
 false, then the implementation could use a simple lookup table:</span></di=
v><div><span style=3D"font-size: 13px;"><br></span></div><div><span style=
=3D"font-size: 13px;">enum Bar {<br>A =3D 1,</span></div><div><span style=
=3D"font-size: 13px;">B =3D 5,</span></div><div><span style=3D"font-size: 1=
3px;">C =3D 8,</span></div><div><span style=3D"font-size: 13px;">D =3D 5</s=
pan></div><div><span style=3D"font-size: 13px;">};</span></div><div><span s=
tyle=3D"font-size: 13px;"><br></span></div><div><span style=3D"font-size: 1=
3px;">for(auto e: enum_range&lt;Bar&gt;()) {}</span></div><div><br></div><d=
iv>constexpr int table[] =3D { 1, 5, 8 }; //Only 3 elements, since D =3D=3D=
 B</div><div>for(int i =3D 0; i &lt; sizeof(table)/sizeof(*table); ++i) {</=
div><div>&nbsp; Bar b =3D Bar(table[i]);<br>}</div><div><span style=3D"font=
-size: 13px;"><br></span></div><div><span style=3D"font-size: 13px;">&nbsp;=
</span><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>...without the extra enum_traits::loop bits. (Actually, if it were/is(?=
)=20
<br>possible to specialize std::begin() on an enum type, with the above=20
<br>and/or N3815 this should already be possible?)
<br></blockquote><div><br></div><div>I'm not sure having begin()/end() on t=
he enum type itself actually makes sense. An enum object is just one tagged=
 object, not the whole collection</div><div><br></div><div>Color color =3D =
kRed;</div><div>for(auto c: color) { /*???*/&nbsp;}&nbsp;</div><blockquote =
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1p=
x #ccc solid;padding-left: 1ex;">
<br>
<br>And actually, another thing I would really like to be able to do (and=
=20
<br>yes, this *does* happen in real code) is:
<br>
<br>for (auto e : std::range(Enum::A, Enum::B, std::range::closed))
<br></blockquote><div>I haven't studied the ranges proposal, but from what =
I think this is supposed to do it looks like a nice feature.</div><div>&nbs=
p;</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>(Oh, look; a case for 'inline enum class' :-).)
<br>
<br>&gt; Other extensions I'd love to see:
<br>&gt; * enum bitmasks as a real type, easy and expressive to declare
<br>
<br>Yes, please!
<br>
<br>For API binary stability, there still needs to be a way to specify exac=
t=20
<br>values. Probably the 'old style' should still be allowed, but it might=
=20
<br>greatly simplify matters to allow e.g. 'foo =3D :5 // equivalent to foo=
 =3D=20
<br>1&lt;&lt;5' (assumes ':0' =3D&gt; 0x1). The main thing that's needed is=
 a way to=20
<br>say that the next value is automatically the highest bit of (2*prev)=20
<br>rather than (prev+1). Unfortunately I don't have a suggestion for that=
=20
<br>syntax.
<br>
<br>I could also see allowing 'foo =3D :2..5' =3D&gt; 0b111100 for ease of=
=20
<br>declaring mask values.
<br></blockquote><div><br></div><div>I'm thinking more something like this:=
</div><div>enum Flags : some_syntax_that_makes_this_a_bitmask_enum {</div><=
div>&nbsp; f1, //Defaults to 1 &lt;&lt; 1</div><div>&nbsp; f2, // 1 &lt;&lt=
; 2</div><div>&nbsp; f3, // 1 &lt;&lt; 3</div><div>&nbsp; f4, // 1 &lt;&lt;=
 4</div><div>&nbsp; f5 =3D 8, //1 &lt;&lt; 8</div><div>&nbsp; f6 =3D 42, //=
1 &lt;&lt; 42, also promotes the unspecified underlying type to at least 64=
 bit integer</div><div>&nbsp; f8 =3D 129, // 1 &lt;&lt; 129, promotes type =
to std::bitset? Or maybe we static_assert here?</div><div>};</div><div>&nbs=
p;</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>&gt; strict
<br>&gt; rules about logical operator comparisons. Only the tags in the enu=
m can use
<br>&gt; binary logical operations with one another.
<br>
<br>This already exists, and has since quite some time; see=20
<br><a href=3D"http://qt-project.org/doc/qt-4.8/qflags.html" target=3D"_bla=
nk" onmousedown=3D"this.href=3D'http://www.google.com/url?q\75http%3A%2F%2F=
qt-project.org%2Fdoc%2Fqt-4.8%2Fqflags.html\46sa\75D\46sntz\0751\46usg\75AF=
QjCNEhWKhlPkQu0A7YA0As8WT67IcsbQ';return true;" onclick=3D"this.href=3D'htt=
p://www.google.com/url?q\75http%3A%2F%2Fqt-project.org%2Fdoc%2Fqt-4.8%2Fqfl=
ags.html\46sa\75D\46sntz\0751\46usg\75AFQjCNEhWKhlPkQu0A7YA0As8WT67IcsbQ';r=
eturn true;">http://qt-project.org/doc/qt-<wbr>4.8/qflags.html</a> (dates b=
ack even to Qt3 I=20
<br>think). I'd love to see a std::flags standardized, however. This=20
<br>shouldn't need language/compiler changes, though (as various parts of=
=20
<br>the above might), just an addition to STL.
<br>
<br>Actually, I have an implementation of this if anyone is interested?
<br></blockquote><div><br></div><div>I'd be interested to know if you chang=
ed your design from qt's qflags and if so why and how that worked out for y=
ou.</div><div>&nbsp;</div><blockquote class=3D"gmail_quote" style=3D"margin=
: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>--=20
<br>Matthew
<br>
<br></blockquote></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_1496_20823269.1389667957344--

.


Author: Tony V E <tvaneerd@gmail.com>
Date: Tue, 14 Jan 2014 05:42:09 -0000
Raw View
--047d7b3a887249519604efe7a727
Content-Type: text/plain; charset=ISO-8859-1

This already exists, and has since quite some time; see
> http://qt-project.org/doc/qt-4.8/qflags.html (dates back even to Qt3 I
> think). I'd love to see a std::flags standardized, however. This
> shouldn't need language/compiler changes, though (as various parts of
> the above might), just an addition to STL.
>
> Actually, I have an implementation of this if anyone is interested?
>

> I'd be interested to know if you changed your design from qt's qflags and
if so why and how that worked out for you.


Yes, this is my question as well. It looks like I may be writing yet
another one of these (can't use qt's for whatever reason) and I've been
wondering about some changes, possibly with help from is_enum<>.
In particular, I would like to get rid of any/all use of macros, for
defining the operators,  etc.

Tony

--

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

--047d7b3a887249519604efe7a727
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<html><head></head><body><br><br><div dir=3D"ltr"><blockquote class=3D"gmai=
l_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pad=
ding-left:1ex">This already exists, and has since quite some time; see=20
<br><a href=3D"http://qt-project.org/doc/qt-4.8/qflags.html" target=3D"_bla=
nk" onmousedown=3D"this.href=3D&#39;http://www.google.com/url?q\75http%3A%2=
F%2Fqt-project.org%2Fdoc%2Fqt-4.8%2Fqflags.html\46sa\75D\46sntz\0751\46usg\=
75AFQjCNEhWKhlPkQu0A7YA0As8WT67IcsbQ&#39;;return true;" onclick=3D"this.hre=
f=3D&#39;http://www.google.com/url?q\75http%3A%2F%2Fqt-project.org%2Fdoc%2F=
qt-4.8%2Fqflags.html\46sa\75D\46sntz\0751\46usg\75AFQjCNEhWKhlPkQu0A7YA0As8=
WT67IcsbQ&#39;;return true;">http://qt-project.org/doc/qt-4.8/qflags.html</=
a> (dates back even to Qt3 I=20
<br>think). I&#39;d love to see a std::flags standardized, however. This=20
<br>shouldn&#39;t need language/compiler changes, though (as various parts =
of=20
<br>the above might), just an addition to STL.
<br>
<br>Actually, I have an implementation of this if anyone is interested?
<br></blockquote><div><br></div><div>&gt; I&#39;d be interested to know if =
you changed your design from qt&#39;s qflags and if so why and how that wor=
ked out for you.</div><div>=A0</div><div><br></div><div>Yes, this is my que=
stion as well. It looks like I may be writing yet another one of these (can=
&#39;t use qt&#39;s for whatever reason) and I&#39;ve been wondering about =
some changes, possibly with help from is_enum&lt;&gt;.</div>
<div>In particular, I would like to get rid of any/all use of macros, for d=
efining the operators, =A0etc.</div><div><br></div><div>Tony</div><div><br>=
</div></div>
</body></html>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--047d7b3a887249519604efe7a727--

.


Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Tue, 14 Jan 2014 00:09:10 -0800 (PST)
Raw View
------=_Part_1803_22277481.1389686950644
Content-Type: text/plain; charset=UTF-8

On Monday, January 13, 2014 7:13:37 PM UTC+1, Matthew Woehlke wrote:
>
> Referring to Andrew's comment, I think most of these that I've seen so
> far and following can be implemented with N3815 and the relaxed
> constexpr rules, but this one might be hard. (I'm not sure how crucial
> it is, however; the bound ones are probably most important... also
> count, but that one is obviously trivial with N3815.)
>

Which one is "this one"?  Do you mean count the distinct values?  I'll
assume so.

First unpack the enumerator values into a constexpr array using an index
sequence as shown in the proposal:

    template<class E>
    constexpr E enumerator_values[] = {
std::enumerator_value<E,i>::value... };

Then we need a set data structure of literal type.  Once you have that you
can simply:

    template<class E>
    constexpr size_t count_distinct_values()
    {
        literal_set<E> S;

        for (E e : enumerator_values)
            S.insert(e);

        return S.size();
    }

    template<class E>
    constexpr size_t distinct_enumerators = count_distinct_enumerators<E>();

This counts the number of distinct values at compile-time.

To implement a set of literal type you can use a hash table with open
addressing.

Here is a similar hash table data structure from an explanation I gave for
a different use case:

    template<class E>
    struct literal_hash_table
    {
        struct entry
        {
            bool occupied = false;
            E key = std::enumerator_value<E,0>;
            size_t position = 0;
        };

        static constexpr size_t num_buckets =
std::enumerator_list_size<E>::value * 2;  // load factor of 2

        entry buckets[num_buckets];
     };

     template<class E>
     constexpr literal_hash_table<E> make_literal_hash_table()
     {
         literal_hash_table<E> table;

         for (size_t i = 0; i < std::enumerator_list_size<E>::value; i++)
         {
              E e = enumerator_values[i];

              size_t hash_code = e % literal_hash_table<E>::num_buckets;

              for (size_t j = hash_code; true; (j++) %=
literal_hash_table<E>::num_buckets)
                  if (!table.buckets[j].occupied)
                  {
                      table.buckets[j].occupied = true;
                      table.buckets[j].key = e;
                      table.buckets[j].position = i;
                  }
          }

          return table;
     };

This one uses the hash table to invert the enumerator value array from
index-to-value, to value-to-index - so implementing a simple literal set is
even easier.

Let me know if you need any further help.

--

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

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

<div dir=3D"ltr">On Monday, January 13, 2014 7:13:37 PM UTC+1, Matthew Woeh=
lke wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:=
 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">Referring to Andrew'=
s comment, I think most of these that I've seen so=20
<br>far and following can be implemented with N3815 and the relaxed=20
<br>constexpr rules, but this one might be hard. (I'm not sure how crucial=
=20
<br>it is, however; the bound ones are probably most important... also=20
<br>count, but that one is obviously trivial with N3815.)
<br>
</blockquote><div><br></div><div>Which one is "this one"? &nbsp;Do you mean=
 count the distinct values? &nbsp;I'll assume so.</div><div><br></div><div>=
First unpack the enumerator values into a constexpr array using an index se=
quence as shown in the proposal:</div><div><br></div><div><font face=3D"cou=
rier new, monospace">&nbsp; &nbsp; template&lt;class E&gt;</font></div><div=
><font face=3D"courier new, monospace">&nbsp; &nbsp; constexpr E enumerator=
_values[] =3D { std::enumerator_value&lt;E,i&gt;::value... };</font></div><=
div><br></div><div>Then we need a set data structure of literal type. &nbsp=
;Once you have that you can simply:</div><div><br></div><div><font face=3D"=
courier new, monospace">&nbsp; &nbsp; template&lt;class E&gt;</font></div><=
div><font face=3D"courier new, monospace">&nbsp; &nbsp; constexpr size_t co=
unt_distinct_values()</font></div><div><font face=3D"courier new, monospace=
">&nbsp; &nbsp; {</font></div><div><font face=3D"courier new, monospace">&n=
bsp; &nbsp; &nbsp; &nbsp; literal_set&lt;E&gt; S;</font></div><div><font fa=
ce=3D"courier new, monospace"><br></font></div><div><font face=3D"courier n=
ew, monospace">&nbsp; &nbsp; &nbsp; &nbsp; for (E e : enumerator_values)<br=
></font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; &nbs=
p; &nbsp; &nbsp; &nbsp; S.insert(e);</font></div><div><font face=3D"courier=
 new, monospace"><br></font></div><div><font face=3D"courier new, monospace=
">&nbsp; &nbsp; &nbsp; &nbsp; return S.size();</font></div><div><font face=
=3D"courier new, monospace">&nbsp; &nbsp; }</font></div><div><font face=3D"=
courier new, monospace"><br></font></div><div><font face=3D"courier new, mo=
nospace">&nbsp; &nbsp; template&lt;class E&gt;</font></div><div><font face=
=3D"courier new, monospace">&nbsp; &nbsp; constexpr size_t distinct_enumera=
tors =3D count_distinct_enumerators&lt;E&gt;();</font></div><div><br></div>=
<div>This counts the number of distinct values at compile-time.</div><div><=
br></div><div>To implement a set of literal type you can use a hash table w=
ith open addressing.</div><div><br></div><div>Here is a similar hash table =
data structure from an explanation I gave for a different use case:</div><d=
iv><br></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; templ=
ate&lt;class E&gt;<br>&nbsp;&nbsp;&nbsp; struct literal_hash_table<br>&nbsp=
;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct entry<=
br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;=
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bool occupied =3D false;<br>&nbs=
p;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; E key =3D st=
d::enumerator_value&lt;E,0&gt;;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbs=
p;&nbsp;&nbsp;&nbsp;&nbsp; size_t position =3D 0;<br>&nbsp;&nbsp;&nbsp;&nbs=
p;&nbsp;&nbsp;&nbsp; };<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s=
tatic constexpr size_t num_buckets =3D std::enumerator_list_size&lt;E&gt;::=
<wbr>value * 2;&nbsp; // load factor of 2<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&n=
bsp;&nbsp;&nbsp; entry buckets[num_buckets];&nbsp;<br>&nbsp;&nbsp;&nbsp;&nb=
sp; };<br><br>&nbsp;&nbsp;&nbsp;&nbsp; template&lt;class E&gt;<br>&nbsp;&nb=
sp;&nbsp;&nbsp; constexpr literal_hash_table&lt;E&gt; make_literal_hash_tab=
le()<br>&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&=
nbsp;&nbsp; literal_hash_table&lt;E&gt; table;<br><br>&nbsp;&nbsp;&nbsp;&nb=
sp;&nbsp;&nbsp;&nbsp;&nbsp; for (size_t i =3D 0; i &lt; std::enumerator_lis=
t_size&lt;E&gt;::<wbr>value; i++)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&n=
bsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp=
;&nbsp;&nbsp;&nbsp; E e =3D enumerator_values[i];<br>&nbsp;&nbsp;&nbsp;&nbs=
p;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nb=
sp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size_=
t hash_code =3D e % literal_hash_table&lt;E&gt;::num_<wbr>buckets;<br><br>&=
nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbs=
p; for (size_t j =3D hash_code; true; (j++) %=3D literal_hash_table&lt;E&gt=
;::num_<wbr>buckets)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb=
sp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!table.buckets[j].o=
ccupied)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb=
sp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb=
sp;&nbsp;&nbsp;&nbsp; table.buckets[j].occupied =3D true;<br>&nbsp;&nbsp;&n=
bsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp=
;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; table.buckets[j].key =3D e;<br>&nbsp;=
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb=
sp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; table.buckets[j].position =3D=
 i;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&n=
bsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp=
;&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbs=
p;&nbsp; return table;<br>&nbsp; &nbsp;&nbsp; };<br></font></div><div><br><=
/div><div>This one uses the hash table to invert the enumerator value array=
 from index-to-value, to value-to-index - so implementing a simple literal =
set is even easier.</div><div><br></div><div>Let me know if you need any fu=
rther help.</div><div><br></div></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_1803_22277481.1389686950644--

.


Author: Matthew Woehlke <mw_triad@users.sourceforge.net>
Date: Tue, 14 Jan 2014 13:49:46 -0500
Raw View
On 2014-01-14 00:42, Tony V E wrote:
>>> This already exists, and has since quite some time; see
>>> http://qt-project.org/doc/qt-4.8/qflags.html (dates back even to Qt3 I
>>> think). I'd love to see a std::flags standardized, however. This
>>> shouldn't need language/compiler changes, though (as various parts of
>>> the above might), just an addition to STL.
>>>
>>> Actually, I have an implementation of this if anyone is interested?
>>
>> I'd be interested to know if you changed your design from qt's qflags and
>> if so why and how that worked out for you.
>
> Yes, this is my question as well. It looks like I may be writing yet
> another one of these (can't use qt's for whatever reason) and I've been
> wondering about some changes, possibly with help from is_enum<>.

I didn't use is_enum. I don't see that it is needed except possibly to
prevent misuse of a non-enum type as the template parameter.

> In particular, I would like to get rid of any/all use of macros, for
> defining the operators,  etc.

Unfortunately this is "not possible". Because the flags type is not
itself the enum type, the desired binary operators taking (Enum, Flag)
must be defined separately from the definition of the Flag template. So
there is no way (AFAIK at least) to avoid a macro except to have to
repeat this code yourself. (Which you could do if you really want to
avoid the macro, but...)

That said, my implementation is just:

   MYPROJECT_FLAGS(EnumType, FlagType)

....which is both the typedef of FlagType and the operators (and can be
used in a namespace scope), rather than two separate macros. (Though,
the first of Qt's macros IIRC is *just* a typedef.)

--
Matthew

--

---
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: Matthew Woehlke <mw_triad@users.sourceforge.net>
Date: Tue, 14 Jan 2014 13:49:56 -0500
Raw View
On 2014-01-13 21:52, fmatthew5876@gmail.com wrote:
> On Monday, January 13, 2014 1:13:37 PM UTC-5, Matthew Woehlke wrote:
>> On 2014-01-11 01:47, fmatth...@gmail.com <javascript:> wrote:
>>> Enums are one of my favorite tools for efficently labeling collections,
>> but
>>> we need to be able to query more information about them.
>>>
>>> I'd like to suggest some form of enum traits.
>>>
>>> template <typename E>
>>> struct enum_traits<E> {
>>>     static_assert(is_enum<E>::value, "Only valid for enums!");
>>>
>>>     typedef /* underlying type */ value_type;
>>>     static constexpr const value_type min =3D /* minimum value of enum =
*/
>>>     static constexpr const value_type max =3D /* maximum value of enum =
*/
>>>     static constexpr const value_type ubound =3D /* maximum value of
>> enum+1.
>>> Not present (does not compile if queried) if max =3D=3D
>>> numeric_limits<value_type>::max(). (Note: this is the most useful
>> value)*/
>>>     static constexpr const size_t count =3D /* Number of enum tags */
>>>     static constexpr const size_t distinct =3D /* Number of enum tags w=
ith
>>> distinct values */
>>
>> Referring to Andrew's comment, I think most of these that I've seen so
>> far and following can be implemented with N3815 and the relaxed
>> constexpr rules, but this one might be hard. (I'm not sure how crucial
>> it is, however; the bound ones are probably most important... also
>> count, but that one is obviously trivial with N3815.)
>
> For iteration, you'd want to only iterate over the distinct values. That
> could require some trickery to get right, which could be optimized away i=
f
> distinct =3D=3D true. I need to sit down and think about implementations =
though.

Hmm... perhaps. That might be worth bringing up w.r.t. N3815, maybe to=20
add a 'distinct' form of the size and value.

>> I wonder how hard to implement the iterators are...
>>
> Second to having enum_strtable, this feature is crucial to me. I use enum=
s
> a lot in C++ and iterating over the values is something I've needed to do
> many times. right now its just the simple for loop with a cast. It would =
be
> nice to have this feature provided by the standard library and be nice an=
d
> type safe.

Don't get me wrong; I agree entirely :-). And actually they're (well,=20
except for above comment) really easy in light of N3815.

>> I would name 'loop' something like 'values' instead. That said, I would
>> really love to just be able to say:
>>
>> enum Enum
>> {
>>     ...
>> };
>> for (auto e : Enum)
>> {
>>     ...
>> }
>
> Enum is a type so this is inventing a whole new syntax (which I am not
> terribly opposed to, less typing is always good). I think its more sensib=
le
> to just create a temporary object and iterate over that, letting the
> compiler optimize away the temporary object and just give you a loop.
>
> Something like this:
>
> template <typename E>
> class enum_range {};
>
> for(auto e: enum_range<Enum>()) { }

Yes, that may be better. If possible to specialize on an enum type=C2=B9,=
=20
even better would be if this can be written:

   for (auto e : std::range<Enum>())

....where the start and end are optional for an enum type. (If specified,=20
presumably they would allow template argument deduction.)

(=C2=B9 If not, I wonder if this should be added...)

>> ...without the extra enum_traits::loop bits. (Actually, if it were/is(?)
>> possible to specialize std::begin() on an enum type, with the above
>> and/or N3815 this should already be possible?)
>
> I'm not sure having begin()/end() on the enum type itself actually makes
> sense. An enum object is just one tagged object, not the whole collection
>
> Color color =3D kRed;
> for(auto c: color) { /*???*/ }

Right. I was still thinking like 'enum E {...}; for (auto e : E)'. But=20
I'm not seeing how you would get that to work without some sort of=20
iterator temporary object, as noted above, as a typename is not a valid=20
token in this context.

>> (Oh, look; a case for 'inline enum class' :-).)
>>
>>> Other extensions I'd love to see:
>>> * enum bitmasks as a real type, easy and expressive to declare
>>
>> Yes, please!
>>
>> For API binary stability, there still needs to be a way to specify exact
>> values. Probably the 'old style' should still be allowed, but it might
>> greatly simplify matters to allow e.g. 'foo =3D :5 // equivalent to foo =
=3D
>> 1<<5' (assumes ':0' =3D> 0x1). The main thing that's needed is a way to
>> say that the next value is automatically the highest bit of (2*prev)
>> rather than (prev+1). Unfortunately I don't have a suggestion for that
>> syntax.
>>
>> I could also see allowing 'foo =3D :2..5' =3D> 0b111100 for ease of
>> declaring mask values.
>>
>
> I'm thinking more something like this:
> enum Flags : some_syntax_that_makes_this_a_bitmask_enum {
>    f1, //Defaults to 1 << 1
>    f2, // 1 << 2
>    f3, // 1 << 3
>    f4, // 1 << 4

Right. Except I assume you meant for the default first value to be '1'=20
(1<<0), not '2' (1<<1) :-). (I tried to make a similar mistake in my=20
above comment.)

>    f5 =3D 8, //1 << 8

This I'd disagree with, because there are times I want an enum value=20
with more than one bit set (e.g. convenience combinations, masks, etc.).=20
Which is why I proposed a new value syntax ' =3D :<bit>' instead. (Also, I=
=20
can imagine it being confusing that '=3D 8' doesn't really mean '8'. Using=
=20
the ':<bit>' syntax, which is the same as already used for bit-packed=20
values, makes it more clear that the number is a bit index and not a raw=20
value.)

>    f6 =3D 42, //1 << 42, also promotes the unspecified underlying type to=
 at
> least 64 bit integer

Naturally :-).

>    f8 =3D 129, // 1 << 129, promotes type to std::bitset? Or maybe we
> static_assert here?

I'd just emit an 'integer constant is too large for its type' warning,=20
same as if it were a regular enum. (Or else make it an error also for=20
regular enums. I don't think it should behave differently, however.)

>>> strict rules about logical operator comparisons. Only the tags in
>>> the enum can use binary logical operations with one another.
>>
>> This already exists, and has since quite some time; see
>> http://qt-project.org/doc/qt-4.8/qflags.html (dates back even to Qt3 I
>> think). I'd love to see a std::flags standardized, however. This
>> shouldn't need language/compiler changes, though (as various parts of
>> the above might), just an addition to STL.
>>
>> Actually, I have an implementation of this if anyone is interested?
>
> I'd be interested to know if you changed your design from qt's qflags and
> if so why and how that worked out for you.

Not significantly. IIRC it needed some tweaking (I think just addition=20
of some explicit casts) to work with strongly-typed (i.e. 'enum class')=20
enums, but otherwise it is essentially the same. Because it is meant to=20
use strongly typed enums, I was able to drop the overloads to prevent=20
combining different enum types.

--=20
Matthew

--=20

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

.


Author: Thiago Macieira <thiago@macieira.org>
Date: Tue, 14 Jan 2014 11:03:47 -0800
Raw View
--nextPart3813120.ySAkN7Zkbk
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset="iso-8859-1"

On ter=E7a-feira, 14 de janeiro de 2014 13:49:46, Matthew Woehlke wrote=
:
> ...which is both the typedef of FlagType and the operators (and can b=
e=20
> used in a namespace scope), rather than two separate macros. (Though,=
=20
> the first of Qt's macros IIRC is *just* a typedef.)

It's also extracted by moc, which handles them specially.
--=20
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
   Software Architect - Intel Open Source Technology Center
      PGP/GPG: 0x6EF45358; fingerprint:
      E067 918B B660 DBD1 105C  966C 33F5 F005 6EF4 5358

--nextPart3813120.ySAkN7Zkbk
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: This is a digitally signed message part.
Content-Transfer-Encoding: 7Bit

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.19 (GNU/Linux)

iD8DBQBS1YoZM/XwBW70U1gRAsXfAJ0Qv5o8SFudLY6ZIqc4geuwiav/rwCeL8dt
P+aCPnoC/TucPCsDpMJ1IfU=
=NOjp
-----END PGP SIGNATURE-----

--nextPart3813120.ySAkN7Zkbk--


.


Author: Sean Middleditch <sean.middleditch@gmail.com>
Date: Tue, 14 Jan 2014 11:23:36 -0800 (PST)
Raw View
------=_Part_359_20828443.1389727416443
Content-Type: text/plain; charset=UTF-8

I brought up a topic on flags support a while ago and some very good
suggestions came out of it; there just hasn't been a formal proposal yet:

https://groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-proposals/flags/std-proposals/1RPxJSJ_0z8/SleWOy2n1HoJ

>
>

--

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

<div dir=3D"ltr">I brought up a topic on flags support a while ago and some=
 very good suggestions came out of it; there just hasn't been a formal prop=
osal yet:<div><br></div><div>https://groups.google.com/a/isocpp.org/forum/?=
fromgroups#!searchin/std-proposals/flags/std-proposals/1RPxJSJ_0z8/SleWOy2n=
1HoJ<br><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><br></blockquote></div=
></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_359_20828443.1389727416443--

.


Author: Matthew Woehlke <mw_triad@users.sourceforge.net>
Date: Tue, 14 Jan 2014 14:25:13 -0500
Raw View
On 2014-01-14 14:03, Thiago Macieira wrote:
> On ter=C3=A7a-feira, 14 de janeiro de 2014 13:49:46, Matthew Woehlke wrot=
e:
>> ...which is both the typedef of FlagType and the operators (and can be
>> used in a namespace scope), rather than two separate macros. (Though,
>> the first of Qt's macros IIRC is *just* a typedef.)
>
> It's also extracted by moc, which handles them specially.

Well, okay, but that's not likely to apply to an STL implementation :-).=20
The point was that if STL were to exactly duplicate Qt's implementation=20
(i.e. with the same two macros doing the same things), the first macro=20
would be a bit superfluous.

For an STL implementation though I would instead propose my one-macro=20
form that declares both the typedef and freestanding operators as one=20
operation. (I'm not sure why Qt does both; probably either for MOC, or=20
due to some requirement from older C++ versions, neither of which would=20
apply to a new STL version.)

--=20
Matthew

--=20

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

.


Author: Thiago Macieira <thiago@macieira.org>
Date: Tue, 14 Jan 2014 12:06:51 -0800
Raw View
On ter=E7a-feira, 14 de janeiro de 2014 14:25:13, Matthew Woehlke wrote:
> For an STL implementation though I would instead propose my one-macro=20
> form that declares both the typedef and freestanding operators as one=20
> operation. (I'm not sure why Qt does both; probably either for MOC, or=20
> due to some requirement from older C++ versions, neither of which would=
=20
> apply to a new STL version.)

One reason is for moc, which like I said extracts the declaration and inclu=
des=20
the information in the meta object.

Another reason is for qdoc, which also extracts the declaration and makes a=
=20
merged documentation for both the enum and the flags type:
 http://qt-project.org/doc/qt-5/qnetworkproxy.html#Capability-enum

From the language point of view, the typedef is not necessary. We could use=
=20
QFlags<EnumType> everywhere. We simply choose not to.

If you're interested in creating a Standard Library type, you may want to t=
ake=20
a look at the most recent changes and discussions on QFlags:
 https://codereview.qt-project.org/60158
 https://codereview.qt-project.org/35324

We're also thinking that we need a separate type for 64-bit enums. One of t=
he=20
reasons for using QFlags at all, besides the nice operators, was to have a=
=20
stable backing type before C++11. Since those enums are still quite common,=
 we=20
need to ensure someone doesn't accidentally grow an enum from 32- to 64-bit=
..

--=20
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
   Software Architect - Intel Open Source Technology Center
      PGP/GPG: 0x6EF45358; fingerprint:
      E067 918B B660 DBD1 105C  966C 33F5 F005 6EF4 5358

--=20

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

.


Author: Matthew Woehlke <mw_triad@users.sourceforge.net>
Date: Tue, 14 Jan 2014 17:43:53 -0500
Raw View
On 2014-01-14 15:06, Thiago Macieira wrote:
>  From the language point of view, the typedef is not necessary. We could use
> QFlags<EnumType> everywhere. We simply choose not to.

Sure. IMHO I'd prefer the named type, but that's into bikeshedding about
the macro (which I'd be okay omitting entirely if it's felt to be
objectionable).

> If you're interested in creating a Standard Library type, you may want to take
> a look at the most recent changes and discussions on QFlags:
>  https://codereview.qt-project.org/60158
>  https://codereview.qt-project.org/35324
>
> We're also thinking that we need a separate type for 64-bit enums. One of the
> reasons for using QFlags at all, besides the nice operators, was to have a
> stable backing type before C++11. Since those enums are still quite common, we
> need to ensure someone doesn't accidentally grow an enum from 32- to 64-bit.

In C++11 I don't think this is needed? In my implementation, the type of
the internal data member is std::underlying_type<Enum>::type, and so is
automatically the correct size. If we're adding it to STL, we can rely
on std::underlying_type being available and should use it.

Thanks also for the links. The first, I'm not sure if it should be
necessary in light of the above (or at worst, shouldn't need more than
to accept both the signed / unsigned versions of the underlying type).
The second is moot per the above.

--
Matthew

--

---
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: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Tue, 14 Jan 2014 17:18:11 -0800 (PST)
Raw View
------=_Part_4694_3049379.1389748691297
Content-Type: text/plain; charset=UTF-8

On Tuesday, January 14, 2014 7:49:56 PM UTC+1, Matthew Woehlke wrote:
>
> On 2014-01-13 21:52, fmatth...@gmail.com <javascript:> wrote:
> > On Monday, January 13, 2014 1:13:37 PM UTC-5, Matthew Woehlke wrote:
> >> On 2014-01-11 01:47, fmatth...@gmail.com <javascript:> wrote:
> >>> Enums are one of my favorite tools for efficently labeling
> collections,
> >> but
> >>> we need to be able to query more information about them.
> >>>
> >>> I'd like to suggest some form of enum traits.
> >>>
> >>> template <typename E>
> >>> struct enum_traits<E> {
> >>>     static_assert(is_enum<E>::value, "Only valid for enums!");
> >>>
> >>>     typedef /* underlying type */ value_type;
> >>>     static constexpr const value_type min = /* minimum value of enum
> */
> >>>     static constexpr const value_type max = /* maximum value of enum
> */
> >>>     static constexpr const value_type ubound = /* maximum value of
> >> enum+1.
> >>> Not present (does not compile if queried) if max ==
> >>> numeric_limits<value_type>::max(). (Note: this is the most useful
> >> value)*/
> >>>     static constexpr const size_t count = /* Number of enum tags */
> >>>     static constexpr const size_t distinct = /* Number of enum tags
> with
> >>> distinct values */
> >>
> >> Referring to Andrew's comment, I think most of these that I've seen so
> >> far and following can be implemented with N3815 and the relaxed
> >> constexpr rules, but this one might be hard. (I'm not sure how crucial
> >> it is, however; the bound ones are probably most important... also
> >> count, but that one is obviously trivial with N3815.)
> >
> > For iteration, you'd want to only iterate over the distinct values. That
> > could require some trickery to get right, which could be optimized away
> if
> > distinct == true. I need to sit down and think about implementations
> though.
>
> Hmm... perhaps. That might be worth bringing up w.r.t. N3815, maybe to
> add a 'distinct' form of the size and value.
>

As shown in my previous message in this thread, using the N3815 property
queries you can determine efficiently at compile-time the number of
distinct values, iterate over the distinct values and/or place the distinct
values in a pack or constexpr array.  You can do this as fast as if the
compiler did it for you, and with only a few lines of pure library code.

There are many use cases for iterating over the full multiset (not just
distinct) of enumerators in declared (or other) order, so no, we are not
dropping support for them.  As the distinct set can be derived from the
full multiset, but not visa versa, the multiset is exposed as the primitive
interface.  This and other issues are explored at length in N3815.

--

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

<div dir=3D"ltr">On Tuesday, January 14, 2014 7:49:56 PM UTC+1, Matthew Woe=
hlke wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left=
: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On 2014-01-13 21:52=
, <a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"VHntqk=
jUHwwJ" onmousedown=3D"this.href=3D'javascript:';return true;" onclick=3D"t=
his.href=3D'javascript:';return true;">fmatth...@gmail.com</a> wrote:
<br>&gt; On Monday, January 13, 2014 1:13:37 PM UTC-5, Matthew Woehlke wrot=
e:
<br>&gt;&gt; On 2014-01-11 01:47, <a>fmatth...@gmail.com</a> &lt;javascript=
:&gt; wrote:
<br>&gt;&gt;&gt; Enums are one of my favorite tools for efficently labeling=
 collections,
<br>&gt;&gt; but
<br>&gt;&gt;&gt; we need to be able to query more information about them.
<br>&gt;&gt;&gt;
<br>&gt;&gt;&gt; I'd like to suggest some form of enum traits.
<br>&gt;&gt;&gt;
<br>&gt;&gt;&gt; template &lt;typename E&gt;
<br>&gt;&gt;&gt; struct enum_traits&lt;E&gt; {
<br>&gt;&gt;&gt; &nbsp; &nbsp; static_assert(is_enum&lt;E&gt;::<wbr>value, =
"Only valid for enums!");
<br>&gt;&gt;&gt;
<br>&gt;&gt;&gt; &nbsp; &nbsp; typedef /* underlying type */ value_type;
<br>&gt;&gt;&gt; &nbsp; &nbsp; static constexpr const value_type min =3D /*=
 minimum value of enum */
<br>&gt;&gt;&gt; &nbsp; &nbsp; static constexpr const value_type max =3D /*=
 maximum value of enum */
<br>&gt;&gt;&gt; &nbsp; &nbsp; static constexpr const value_type ubound =3D=
 /* maximum value of
<br>&gt;&gt; enum+1.
<br>&gt;&gt;&gt; Not present (does not compile if queried) if max =3D=3D
<br>&gt;&gt;&gt; numeric_limits&lt;value_type&gt;::<wbr>max(). (Note: this =
is the most useful
<br>&gt;&gt; value)*/
<br>&gt;&gt;&gt; &nbsp; &nbsp; static constexpr const size_t count =3D /* N=
umber of enum tags */
<br>&gt;&gt;&gt; &nbsp; &nbsp; static constexpr const size_t distinct =3D /=
* Number of enum tags with
<br>&gt;&gt;&gt; distinct values */
<br>&gt;&gt;
<br>&gt;&gt; Referring to Andrew's comment, I think most of these that I've=
 seen so
<br>&gt;&gt; far and following can be implemented with N3815 and the relaxe=
d
<br>&gt;&gt; constexpr rules, but this one might be hard. (I'm not sure how=
 crucial
<br>&gt;&gt; it is, however; the bound ones are probably most important... =
also
<br>&gt;&gt; count, but that one is obviously trivial with N3815.)
<br>&gt;
<br>&gt; For iteration, you'd want to only iterate over the distinct values=
.. That
<br>&gt; could require some trickery to get right, which could be optimized=
 away if
<br>&gt; distinct =3D=3D true. I need to sit down and think about implement=
ations though.
<br>
<br>Hmm... perhaps. That might be worth bringing up w.r.t. N3815, maybe to=
=20
<br>add a 'distinct' form of the size and value.
<br>
</blockquote><div><br></div><div>As shown in my previous message in this th=
read, using the N3815 property queries you can determine efficiently at com=
pile-time the number of distinct values, iterate over the distinct values a=
nd/or place the distinct values in a pack or constexpr array. &nbsp;You can=
 do this as fast as if the compiler did it for you, and with only a few lin=
es of pure library code.</div><div><br></div><div>There are many use cases =
for iterating over the full multiset (not just distinct) of enumerators in =
declared (or other) order, so no, we are not dropping support for them. &nb=
sp;As the distinct set can be derived from the full multiset, but not visa =
versa, the multiset is exposed as the primitive interface. &nbsp;This and o=
ther issues are explored at length in N3815.</div><div><br></div></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_4694_3049379.1389748691297--

.


Author: Thiago Macieira <thiago@macieira.org>
Date: Tue, 14 Jan 2014 17:37:22 -0800
Raw View
On ter=E7a-feira, 14 de janeiro de 2014 17:43:53, Matthew Woehlke wrote:
> > If you're interested in creating a Standard Library type, you may want =
to
> > take>=20
> > a look at the most recent changes and discussions on QFlags:
> >  https://codereview.qt-project.org/60158
> >  https://codereview.qt-project.org/35324
> >=20
> > We're also thinking that we need a separate type for 64-bit enums. One =
of
> > the reasons for using QFlags at all, besides the nice operators, was to
> > have a stable backing type before C++11. Since those enums are still
> > quite common, we need to ensure someone doesn't accidentally grow an en=
um
> > from 32- to 64-bit.
> In C++11 I don't think this is needed? In my implementation, the type of
> the internal data member is std::underlying_type<Enum>::type, and so is
> automatically the correct size. If we're adding it to STL, we can rely
> on std::underlying_type being available and should use it.
>=20
> Thanks also for the links. The first, I'm not sure if it should be
> necessary in light of the above (or at worst, shouldn't need more than
> to accept both the signed / unsigned versions of the underlying type).
> The second is moot per the above.

It isn't necessary if the underlying enum type has an explicit size:

 enum Flag : int {
  Opt1 =3D 1,
  Opt2 =3D 2
 };
 // the "class" keyword is not necessary to use this feature

But what happens if the user forgets the explicit type, chooses not to use =
it,=20
or is creating flags for a type that he doesn't control?

 enum Flag2 {
  Opt1 =3D 1,
  Opt2 =3D 2
 };

 According to the standard, the enum will be backed by any integer large=20
enough to hold all values. In the example above, it could be as small as a=
=20
char.

In practice, compilers will usually choose int as the smallest type, then g=
row=20
to unsigned int, long, unsigned long, long long, unsigned long long. So=20
there's little danger of types smaller than 32-bit, but there's still the=
=20
danger of growing it accidentally to 64-bit.

I mean, the above is most likely=20
 sizeof(Flag2) =3D=3D sizeof(std::flags<Flag2>) =3D=3D sizeof(int)

But what happens if in my new version I do change Flag2 to be:

 enum Flag2 {
  Opt1 =3D 1,
  Opt2 =3D 2,
  Invalid =3D ~0L // the L looks nice and I don't know the consequences
 };

Now sizeof(Flag2) =3D=3D sizeof(std::flags<Flag2>) =3D=3D sizeof(long).

The Standard Library does not need to care about this -- after all, binary=
=20
compatibility issues are beyond the scope of the standard. But it's somethi=
ng=20
we care about in Qt and one of the reasons why we introduced QFlags in the=
=20
first place.

--=20
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
   Software Architect - Intel Open Source Technology Center
      PGP/GPG: 0x6EF45358; fingerprint:
      E067 918B B660 DBD1 105C  966C 33F5 F005 6EF4 5358

--=20

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

.


Author: Matthew Woehlke <mw_triad@users.sourceforge.net>
Date: Wed, 15 Jan 2014 12:16:38 -0500
Raw View
On 2014-01-14 20:37, Thiago Macieira wrote:
>  enum Flag2 {
>   Opt1 = 1,
>   Opt2 = 2
>  };
>
> I mean, the above is most likely
>  sizeof(Flag2) == sizeof(std::flags<Flag2>) == sizeof(int)
>
> But what happens if in my new version I do change Flag2 to be:
>
>  enum Flag2 {
>   Opt1 = 1,
>   Opt2 = 2,
>   Invalid = ~0L // the L looks nice and I don't know the consequences
>  };
>
> Now sizeof(Flag2) == sizeof(std::flags<Flag2>) == sizeof(long).

....and so any code that took Flag2 is now (BC) broken, yes?

> The Standard Library does not need to care about this -- after all, binary
> compatibility issues are beyond the scope of the standard. But it's something
> we care about in Qt and one of the reasons why we introduced QFlags in the
> first place.

I guess I'm not convinced that std::flags needs to enforce a stronger BC
guarantee than the underlying type. If you want to ensure BC, specify
the storage type of the underlying enum.

--
Matthew

--

---
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: Tony V E <tvaneerd@gmail.com>
Date: Wed, 15 Jan 2014 13:34:19 -0500
Raw View
--001a11336d909839aa04f0068eeb
Content-Type: text/plain; charset=ISO-8859-1

On Tue, Jan 14, 2014 at 1:49 PM, Matthew Woehlke <
mw_triad@users.sourceforge.net> wrote:

>
>
> In particular, I would like to get rid of any/all use of macros, for
>> defining the operators,  etc.
>>
>
> Unfortunately this is "not possible". Because the flags type is not itself
> the enum type, the desired binary operators taking (Enum, Flag) must be
> defined separately from the definition of the Flag template. So there is no
> way (AFAIK at least) to avoid a macro except to have to repeat this code
> yourself. (Which you could do if you really want to avoid the macro, but...)
>
>
This is the basis of what I'm experimenting with:


template <typename Enum>
struct EnumFlags
{
    typedef typename make_unsigned<underlying_type<Enum>::type>::type
value_type;
    value_type val;

    EnumFlags(Enum e) : val(e) {}

    operator value_type() { return val; }

    // *most* of the operators
    friend EnumFlags operator|(EnumFlags a, EnumFlags b)
    {
        return EnumFlags(value(a) | value(b));
    }
    friend EnumFlags operator|(EnumFlags a, Enum b)
    {
        return EnumFlags(value(a) | value(b));
    }
    friend EnumFlags operator|(Enum a, EnumFlags b)
    {
        return EnumFlags(value(a) | value(b));
    }
    // but, unfortunately, Enum | Enum must be outside the class. See
below...
};

// now here is the scary part:

template <typename Enum>
typename enable_if< is_enum<Enum>::value, EnumFlags<Enum> >::type
operator|(Enum a, Enum b)
{
    return
EnumFlags<Enum>(static_cast<Enum>(static_cast<EnumFlags<Enum>::value_type>(a)
| b));
}

So that defines operator|() for ALL enums, whether or not you want it.
Thus it is the "scary part".

Note, that:

enum Breakfast { Ham, Eggs, Green };

unsigned int x = Green | Eggs | Ham;

still works, but it converts it temporarily to EnumFlags<Breakfast>, then
to unsigned int via the cast operator. Whether you want it to or not.  Not
_usually_ a problem, however:

struct ConvertsToInt
{
    ConvertsToInt(unsigned int);
};

void func(ConvertsToInt);

int main()
{
    func(Green | Eggs | Ham); // no longer works - too many conversions :-(
}


So that overly-broad operator|(Enum a, Enum b) is dangerous.  But might be
OK for a code-base where you don't want to allow things like that.

Alternatively, you can replace the use of is_enum<> with something like
wants_enumflags<>.  And then you specialize to say you want it:

    template <> wants_enumflags<Breakfast> : true_type;

but I'm sure most people would prefer to have that in a macro.
MYPROJECT_ENUMFLAGS(Breakfast) or Q_DECLARE_OPERATORS_FOR_FLAGS(Breakfast).
:-(

Tony




> That said, my implementation is just:
>
>   MYPROJECT_FLAGS(EnumType, FlagType)
>
> ...which is both the typedef of FlagType and the operators (and can be
> used in a namespace scope), rather than two separate macros. (Though, the
> first of Qt's macros IIRC is *just* a typedef.)
>
>
> --
> Matthew
>
> --
>
> --- 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/.
>

--

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

--001a11336d909839aa04f0068eeb
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><br><div class=3D"gmail=
_quote">On Tue, Jan 14, 2014 at 1:49 PM, Matthew Woehlke <span dir=3D"ltr">=
&lt;<a href=3D"mailto:mw_triad@users.sourceforge.net" target=3D"_blank">mw_=
triad@users.sourceforge.net</a>&gt;</span> wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left:1px solid rgb(204,204,204);padding-left:1ex"><br>
<div class=3D"im"><br><blockquote class=3D"gmail_quote" style=3D"margin:0px=
 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
In particular, I would like to get rid of any/all use of macros, for<br>
defining the operators, =A0etc.<br>
</blockquote>
<br></div>
Unfortunately this is &quot;not possible&quot;. Because the flags type is n=
ot itself the enum type, the desired binary operators taking (Enum, Flag) m=
ust be defined separately from the definition of the Flag template. So ther=
e is no way (AFAIK at least) to avoid a macro except to have to repeat this=
 code yourself. (Which you could do if you really want to avoid the macro, =
but...)<br>

<br></blockquote><div><br></div><div>This is the basis of what I&#39;m expe=
rimenting with:<br><br><br></div>template &lt;typename Enum&gt;<br><div>str=
uct EnumFlags<br>{<br></div><div>=A0=A0=A0 typedef typename make_unsigned&l=
t;underlying_type&lt;Enum&gt;::type&gt;::type value_type;<br>
</div><div>=A0=A0=A0 value_type val;<br></div><div><br></div><div>=A0=A0=A0=
 EnumFlags(Enum e) : val(e) {}<br><br></div><div>=A0=A0=A0 operator value_t=
ype() { return val; }<br><br></div><div>=A0=A0=A0 // *most* of the operator=
s<br></div><div>=A0=A0=A0 friend EnumFlags operator|(EnumFlags a, EnumFlags=
 b)<br>
=A0=A0=A0 {<br>=A0=A0=A0=A0=A0=A0=A0 return EnumFlags(value(a) | value(b));=
<br>=A0=A0=A0 }<br>=A0=A0=A0 friend EnumFlags operator|(EnumFlags a, Enum b=
)<br>=A0=A0=A0 {<br>=A0=A0=A0=A0=A0=A0=A0 return EnumFlags(value(a) | value=
(b));<br>=A0=A0=A0 }<br>=A0=A0=A0 friend EnumFlags operator|(Enum a, EnumFl=
ags b)<br>
=A0=A0=A0 {<br>=A0=A0=A0=A0=A0=A0=A0 return EnumFlags(value(a) | value(b));=
<br>=A0=A0=A0 }<br></div><div>=A0=A0=A0 // but, unfortunately, Enum | Enum =
must be outside the class. See below...<br></div><div>};<br></div><div><br>=
</div><div>// now here is the scary part:<br>
<br></div><div>template &lt;typename Enum&gt;<br>typename enable_if&lt; is_=
enum&lt;Enum&gt;::value, EnumFlags&lt;Enum&gt; &gt;::type=A0=A0 operator|(E=
num a, Enum b)<br>{<br>=A0=A0=A0 return EnumFlags&lt;Enum&gt;(static_cast&l=
t;Enum&gt;(static_cast&lt;EnumFlags&lt;Enum&gt;::value_type&gt;(a) | b));<b=
r>
}<br><br></div><div>So that defines operator|() for ALL enums, whether or n=
ot you want it.=A0 Thus it is the &quot;scary part&quot;.<br><br>Note, that=
:<br><br></div><div>enum Breakfast { Ham, Eggs, Green };<br><br></div><div>
unsigned int x =3D Green | Eggs | Ham;<br><br></div><div>still works, but i=
t converts it temporarily to EnumFlags&lt;Breakfast&gt;, then to unsigned i=
nt via the cast operator. Whether you want it to or not.=A0 Not _usually_ a=
 problem, however:<br>
<br></div><div>struct ConvertsToInt<br>{<br></div><div>=A0=A0=A0 ConvertsTo=
Int(unsigned int);<br>};<br><br></div><div>void func(ConvertsToInt);<br><br=
></div><div>int main()<br>{<br></div><div>=A0=A0=A0 func(Green | Eggs | Ham=
); // no longer works - too many conversions :-(<br>
}<br><br><br></div><div>So that overly-broad operator|(Enum a, Enum b) is d=
angerous.=A0 But might be OK for a code-base where you don&#39;t want to al=
low things like that.<br><br>Alternatively, you can replace the use of is_e=
num&lt;&gt; with something like wants_enumflags&lt;&gt;.=A0 And then you sp=
ecialize to say you want it:<br>
<br></div><div>=A0=A0=A0 template &lt;&gt; wants_enumflags&lt;Breakfast&gt;=
 : true_type;<br><br></div><div>but I&#39;m sure most people would prefer t=
o have that in a macro. MYPROJECT_ENUMFLAGS(Breakfast) or Q_DECLARE_OPERATO=
RS_FOR_FLAGS(Breakfast).<br>
:-(<br><br></div><div>Tony<br><br></div><div><br></div><div>=A0</div><block=
quote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1=
px solid rgb(204,204,204);padding-left:1ex">
That said, my implementation is just:<br>
<br>
=A0 MYPROJECT_FLAGS(EnumType, FlagType)<br>
<br>
....which is both the typedef of FlagType and the operators (and can be used=
 in a namespace scope), rather than two separate macros. (Though, the first=
 of Qt&#39;s macros IIRC is *just* a typedef.)<div class=3D""><div class=3D=
"h5">
<br>
<br>
-- <br>
Matthew<br>
<br>
-- <br>
<br>
--- You received this message because you are subscribed to the Google Grou=
ps &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%2Bunsubscribe@isocpp.org" target=3D=
"_blank">std-proposals+unsubscribe@<u></u>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/<u></u>isocpp.=
org/group/std-<u></u>proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--001a11336d909839aa04f0068eeb--

.


Author: Matthew Woehlke <mw_triad@users.sourceforge.net>
Date: Wed, 15 Jan 2014 14:19:00 -0500
Raw View
This is a multi-part message in MIME format.
--------------070303020309060104020709
Content-Type: text/plain; charset=UTF-8; format=flowed

On 2014-01-15 13:34, Tony V E wrote:
> On Tue, Jan 14, 2014 at 1:49 PM, Matthew Woehlke wrote:
>>> In particular, I would like to get rid of any/all use of macros, for
>>> defining the operators,  etc.
>>
>> Unfortunately this is "not possible". Because the flags type is not itself
>> the enum type, the desired binary operators taking (Enum, Flag) must be
>> defined separately from the definition of the Flag template. So there is no
>> way (AFAIK at least) to avoid a macro except to have to repeat this code
>> yourself. (Which you could do if you really want to avoid the macro, but...)
>
> This is the basis of what I'm experimenting with:
> [snip implementation]

Er... I'll omit specific comments, and just say that there is a *lot*
missing there.

I attached the version I'm using, with some attempt to rewrite it as an
actual reference implementation (please pardon any style errors). I
didn't change it to use make_unsigned as you did... I'm not sure if
that's desirable, as it can lead to signed/unsigned mismatch because the
internal type of the std::flags != the enum type. (Also, I added an
explicit operator~ for the enum type which should ensure that e.g.
'~enum::value' always has the same type as std::flags<enum>::value_t and
thus won't trigger type conversions using as input to std::flags's
operators.)

> // now here is the scary part:
>
> template <typename Enum>
> typename enable_if< is_enum<Enum>::value, EnumFlags<Enum> >::type
> operator|(Enum a, Enum b)
> {
>      return
> EnumFlags<Enum>(static_cast<Enum>(static_cast<EnumFlags<Enum>::value_type>(a)
> | b));
> }

Er... yes. Let's not do that. Globally defining operator| for any enum
(in case someone has done '#include <flags>' anyway) seems dangerous.

--
Matthew

--

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

--------------070303020309060104020709
Content-Type: text/plain; charset=UTF-8;
 name="c++1y-std-flags.h"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="c++1y-std-flags.h"

Ly8gaGVhZGVyIGd1YXJkIGVsaWRlZAoKI2luY2x1ZGUgPHR5cGVfdHJhaXRzPgoKbmFtZXNw
YWNlIHN0ZAp7CiAgdGVtcGxhdGUgPHR5cGVuYW1lIEVudW0+IGNsYXNzIGZsYWdzCiAgewog
ICAgc3RhdGljX2Fzc2VydChzdGQ6OmlzX2VudW08RW51bT46OnZhbHVlLAogICAgICAgICAg
ICAgICAgICAic3RkOjpmbGFncyBtYXkgb25seSBiZSB1c2VkIG9uIGVudW0gdHlwZXMiKTsK
CiAgcHVibGljOgogICAgdXNpbmcgdmFsdWVfdCA9IHR5cGVuYW1lIHN0ZDo6dW5kZXJseWlu
Z190eXBlPEVudW0+Ojp0eXBlOwoKICAgIC8vIGNvbnN0cnVjdG9ycwogICAgY29uc3RleHBy
IGZsYWdzKCkgOiB2YWx1ZXswfSB7fQogICAgY29uc3RleHByIGZsYWdzKHN0ZDo6bnVsbHB0
cl90KSA6IHZhbHVlezB9IHt9CiAgICBjb25zdGV4cHIgZmxhZ3MoRW51bSBmKSA6IHZhbHVl
KHN0YXRpY19jYXN0PHZhbHVlX3Q+KGYpKSB7fQogICAgY29uc3RleHByIGZsYWdzKGZsYWdz
IGNvbnN0JikgPSBkZWZhdWx0OwoKICAgIC8vIGFzc2lnbm1lbnQKICAgIGZsYWdzJiBvcGVy
YXRvcj0oZmxhZ3MgY29uc3QmKSA9IGRlZmF1bHQ7CgogICAgZmxhZ3MmIG9wZXJhdG9yPShF
bnVtIGYpCiAgICB7IHZhbHVlID0gc3RhdGljX2Nhc3Q8dmFsdWVfdD4oZik7IHJldHVybiAq
dGhpczsgfQoKICAgIGZsYWdzJiBvcGVyYXRvcj0oc3RkOjpudWxscHRyX3QpCiAgICB7IHZh
bHVlID0gMDsgcmV0dXJuICp0aGlzOyB9CgogICAgLy8gY29udmVyc2lvbiBvcGVyYXRvcgog
ICAgY29uc3RleHByIG9wZXJhdG9yIHZhbHVlX3QoKSBjb25zdCB7IHJldHVybiB2YWx1ZTsg
fQoKICAgIC8vIGNvbXBhcmlzb24gb3BlcmF0b3IKICAgIGNvbnN0ZXhwciBib29sIG9wZXJh
dG9yPT0oRW51bSBmKSBjb25zdAogICAgeyByZXR1cm4gdmFsdWUgPT0gZmxhZ3N7Zn07IH0K
CiAgICAvLyAnJicgb3BlcmF0b3JzCiAgICBjb25zdGV4cHIgZmxhZ3Mgb3BlcmF0b3ImKHZh
bHVlX3QgbSkgY29uc3QKICAgIHsgcmV0dXJuIHt2YWx1ZSAmIG19OyB9CgogICAgZmxhZ3Mm
IG9wZXJhdG9yJj0odmFsdWVfdCBtKQogICAgeyB2YWx1ZSAmPSBtOyByZXR1cm4gKnRoaXM7
IH0KCiAgICBjb25zdGV4cHIgZmxhZ3Mgb3BlcmF0b3ImKEVudW0gZikgY29uc3QKICAgIHsg
cmV0dXJuIHt2YWx1ZSAmIHN0YXRpY19jYXN0PHZhbHVlX3Q+KGYpfTsgfQoKICAgIGZsYWdz
JiBvcGVyYXRvciY9KEVudW0gZikKICAgIHsgdmFsdWUgJj0gc3RhdGljX2Nhc3Q8dmFsdWVf
dD4oZik7IHJldHVybiAqdGhpczsgfQoKICAgIC8vICd8JyBvcGVyYXRvcnMKICAgIGNvbnN0
ZXhwciBmbGFncyBvcGVyYXRvcnwoZmxhZ3Mgb3RoZXIpCiAgICB7IHJldHVybiB7dmFsdWUg
fCBvdGhlci52YWx1ZX07IH0KCiAgICBmbGFncyYgb3BlcmF0b3J8PShmbGFncyBvdGhlcikK
ICAgIHsgdmFsdWUgfD0gb3RoZXIudmFsdWU7IHJldHVybiAqdGhpczsgfQoKICAgIGNvbnN0
ZXhwciBmbGFncyBvcGVyYXRvcnwoRW51bSBmKQogICAgeyByZXR1cm4ge3ZhbHVlIHwgc3Rh
dGljX2Nhc3Q8dmFsdWVfdD4oZil9OyB9CgogICAgZmxhZ3MmIG9wZXJhdG9yfD0oRW51bSBm
KQogICAgeyB2YWx1ZSB8PSBzdGF0aWNfY2FzdDx2YWx1ZV90PihmKTsgcmV0dXJuICp0aGlz
OyB9CgogICAgLy8gJ14nIG9wZXJhdG9ycwogICAgY29uc3RleHByIGZsYWdzIG9wZXJhdG9y
XihmbGFncyBvdGhlcikKICAgIHsgcmV0dXJuIHt2YWx1ZSBeIG90aGVyLnZhbHVlfTsgfQoK
ICAgIGZsYWdzJiBvcGVyYXRvcl49KGZsYWdzIG90aGVyKQogICAgeyB2YWx1ZSBePSBvdGhl
ci52YWx1ZTsgcmV0dXJuICp0aGlzOyB9CgogICAgY29uc3RleHByIGZsYWdzIG9wZXJhdG9y
XihFbnVtIGYpCiAgICB7IHJldHVybiB7dmFsdWUgXiBzdGF0aWNfY2FzdDx2YWx1ZV90Pihm
KX07IH0KCiAgICBmbGFncyYgb3BlcmF0b3JePShFbnVtIGYpCiAgICB7IHZhbHVlIF49IHN0
YXRpY19jYXN0PHZhbHVlX3Q+KGYpOyByZXR1cm4gKnRoaXM7IH0KCiAgICAvLyBvdGhlciBv
cGVyYXRvcnMKICAgIGNvbnN0ZXhwciB2YWx1ZV90IG9wZXJhdG9yfigpIGNvbnN0IHsgcmV0
dXJuIH52YWx1ZTsgfQoKICAgIGNvbnN0ZXhwciBib29sIG9wZXJhdG9yISgpIGNvbnN0IHsg
cmV0dXJuICF2YWx1ZTsgfQoKICAgIC8vIHRlc3QgZmxhZwogICAgY29uc3RleHByIGJvb2wg
dGVzdChFbnVtIGYpIGNvbnN0CiAgICB7CiAgICAgIHJldHVybiAoKCp0aGlzICYgZikgPT0g
ZikgJiYKICAgICAgICAgICAgICAoKHN0YXRpY19jYXN0PHZhbHVlX3Q+KGYpICE9IDApIHx8
ICh2YWx1ZSA9PSAwKSk7CiAgICB9CgogICAgLy8gY2xlYXIgZmxhZyAvIGFsbAogICAgdm9p
ZCBjbGVhcigpIHsgdmFsdWUgPSAwOyB9CiAgICB2b2lkIGNsZWFyKEVudW0gZikgeyB2YWx1
ZSAmPSB+c3RhdGljX2Nhc3Q8dmFsdWVfdD4oZik7IH0KICAgIHZvaWQgY2xlYXIodmFsdWVf
dCBtKSB7IHZhbHVlICY9IH5tOyB9CgogIHByb3RlY3RlZDoKICAgIGNvbnN0ZXhwciBmbGFn
cyh2YWx1ZV90IHYpIDogdmFsdWV7dn0ge30KICAgIHZhbHVlX3QgdmFsdWU7CiAgfTsKCn0K
Ci8vIERlY2xhcmUganVzdCB0aGUgb3BlcmF0b3JzIGZvciBhIGZsYWdzIHR5cGUKI2RlZmlu
ZSBTVERfT1BFUkFUT1JTX0ZPUl9GTEFHUyhfZW51bSkgXAogIGNvbnN0ZXhwciBpbmxpbmUg
OjpzdGQ6OmZsYWdzPF9lbnVtPiBvcGVyYXRvcnwoX2VudW0gZjEsIF9lbnVtIGYyKSBcCiAg
eyByZXR1cm4gOjpzdGQ6OmZsYWdzPF9lbnVtPntmMX0gfCBmMjsgfSBcCiAgY29uc3RleHBy
IGlubGluZSA6OnN0ZDo6ZmxhZ3M8X2VudW0+IG9wZXJhdG9yfChfZW51bSBmMSwgOjpzdGQ6
OmZsYWdzPF9lbnVtPiBmMikgXAogIHsgcmV0dXJuIGYyIHwgZjE7IH0gXAogIGNvbnN0ZXhw
ciBpbmxpbmUgYXV0byBvcGVyYXRvcn4oX2VudW0gZikgLT4gc3RkOjp1bmRlcmx5aW5nX3R5
cGU8X2VudW0+Ojp0eXBlIFwKICB7IFwKICAgIHN0YXRpY19hc3NlcnQoc3RkOjppc19lbnVt
PF9lbnVtPjo6dmFsdWUsIFwKICAgICAgICAgICAgICAgICAgIlNURF9PUEVSQVRPUlNfRk9S
X0ZMQUdTIG1heSBvbmx5IGJlIHVzZWQgb24gZW51bSB0eXBlcyIpOyBcCiAgICByZXR1cm4g
fnN0YXRpY19jYXN0PHN0ZDo6dW5kZXJseWluZ190eXBlPF9lbnVtPjo6dHlwZT4oZik7IFwK
ICB9CgovLyBEZWNsYXJlIG9wZXJhdG9ycyBhbmQgdHlwZSBhbGlhcyBmb3IgZmxhZ3MKI2Rl
ZmluZSBTVERfRkxBR1MoX2ZsYWdzLCBfZW51bSkgXAogIHVzaW5nIF9mbGFncyA9IDo6c3Rk
OjpmbGFnczxfZW51bT47IFwKICBTVERfT1BFUkFUT1JTX0ZPUl9GTEFHUyhfZW51bSkK
--------------070303020309060104020709--


.


Author: Matthew Woehlke <mw_triad@users.sourceforge.net>
Date: Wed, 15 Jan 2014 14:54:36 -0500
Raw View
On 2014-01-15 14:19, Matthew Woehlke wrote:
> On 2014-01-15 13:34, Tony V E wrote:
>> On Tue, Jan 14, 2014 at 1:49 PM, Matthew Woehlke wrote:
>>>> In particular, I would like to get rid of any/all use of macros, for
>>>> defining the operators,  etc.
>>>
>>> Unfortunately this is "not possible". Because the flags type is not
>>> itself
>>> the enum type, the desired binary operators taking (Enum, Flag) must be
>>> defined separately from the definition of the Flag template. So there
>>> is no
>>> way (AFAIK at least) to avoid a macro except to have to repeat this code
>>> yourself. (Which you could do if you really want to avoid the macro,
>>> but...)
>>
>> This is the basis of what I'm experimenting with:
>> [snip implementation]
>
> Er... I'll omit specific comments, and just say that there is a *lot*
> missing there.
>
> I attached the version I'm using, with some attempt to rewrite it as an
> actual reference implementation (please pardon any style errors). I
> didn't change it to use make_unsigned as you did... I'm not sure if
> that's desirable, as it can lead to signed/unsigned mismatch because the
> internal type of the std::flags != the enum type. (Also, I added an
> explicit operator~ for the enum type which should ensure that e.g.
> '~enum::value' always has the same type as std::flags<enum>::value_t and
> thus won't trigger type conversions using as input to std::flags's
> operators.)

Here's a modest example of the previous code in action:

#include <flags>

enum class bit // 'class' is optional, can also use old-style enum
{
     A = 1<<0,
     B = 1<<1,
     C = 1<<2,
};
// STD_OPERATORS_FOR_FLAGS(bit) if you don't want the typedef
STD_FLAGS(bitset, bit) // as above, plus alias bitset = std::flags<bit>

int main()
{
     auto x = std::flags<int>{}; // error: 'int' is not an enum type
     auto i = bitset{5}; // error: ctor is protected
     auto z = bitset{0}; // okay, calls bitset(nullptr_t)

     auto b = bitset{bit::A};
     auto m = ~bit::B; // okay, use custom operator~(bit)
     b &= m; // typeof(m) == std::flags<bit>::value_t

     return 0;
}

Unlike QFlags, it works on both 'enum' (old-style enum) and 'enum class'
(new, type-safe enum). There is no mucking about with an 'incompatible
flags' type (but note that this means you can do some 'wrong'/'abusive'
things with a non-type-safe enum, though the resulting integer type
can't be put back into a std::flags).

The use of a ctor taking nullptr_t isn't ideal, but I really want to be
able to zero-initialize a std::flags (i.e. literal "= 0" and variations
thereof), and this seems the best way without a language change.

p.s. I consider having separate types for individual flag values and the
flag collection to be a feature, not a detriment :-).

I'll declare the exact method of declaring the freestanding operators to
be a matter of bikeshedding. I used a macro, but Tony's suggestion re:
conditional templates ('wants_flags') would work as well.

Another option would be if we added a language feature to test if a
template instantiation exists without instantiating it, i.e. at the
point the compiler needs to instantiate e.g. operator|(flag_t, flag_t)
it would test if 'std::flags<flag_t>' has been used prior to that point.
This would make the freestanding operators 'automagic'.

(Note that I'm considering any/all issues regarding more convenient
definition of flag values to be orthogonal.)

--
Matthew

--

---
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: Greg Marr <gregmmarr@gmail.com>
Date: Thu, 16 Jan 2014 14:25:43 -0800 (PST)
Raw View
------=_Part_622_22744695.1389911143386
Content-Type: text/plain; charset=UTF-8

On Monday, January 13, 2014 1:13:37 PM UTC-5, Matthew Woehlke wrote:
>
> On 2014-01-11 01:47, fmatth...@gmail.com <javascript:> wrote:
> >    static constexpr const bool is_contiguious = /* true if enum values
> are
> > contiguous */
> >    static constexpr const bool is_regular = is_contiguous && min ==
> > value_type(0);
> >    static constexpr const bool has_zero = /* true if zero is an enum
> value */
> >    static constexpr const bool has_postive = /* true if at least one
> enum
> > value is positive */
> >    static constexpr const bool all_postive = /* true if all enum values
> are
> > positive */
>
> This feels like 'all_nonnegative' is missing...
>
> >    static constexpr const bool has_negative = /* true if at least one
> enum
> > value is negative */
>

It's covered in the negative sense:
    all_nonnegative() == !has_negative()

For that matter, all_positive is already covered too:
    all_positive() == !has_zero() && !has_negative()

I noticed three typos in the quoted section: is_contiguious, has_postive,
all_postive

--

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

<div dir=3D"ltr">On Monday, January 13, 2014 1:13:37 PM UTC-5, Matthew Woeh=
lke wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:=
 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On 2014-01-11 01:47,=
 <a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"HO5p37r=
XGswJ" onmousedown=3D"this.href=3D'javascript:';return true;" onclick=3D"th=
is.href=3D'javascript:';return true;">fmatth...@gmail.com</a> wrote:
<br>&gt; &nbsp; &nbsp;static constexpr const bool is_contiguious =3D /* tru=
e if enum values are
<br>&gt; contiguous */
<br>&gt; &nbsp; &nbsp;static constexpr const bool is_regular =3D is_contigu=
ous &amp;&amp; min =3D=3D
<br>&gt; value_type(0);
<br>&gt; &nbsp; &nbsp;static constexpr const bool has_zero =3D /* true if z=
ero is an enum value */
<br>&gt; &nbsp; &nbsp;static constexpr const bool has_postive =3D /* true i=
f at least one enum
<br>&gt; value is positive */
<br>&gt; &nbsp; &nbsp;static constexpr const bool all_postive =3D /* true i=
f all enum values are
<br>&gt; positive */
<br>
<br>This feels like 'all_nonnegative' is missing...
<br>
<br>&gt; &nbsp; &nbsp;static constexpr const bool has_negative =3D /* true =
if at least one enum
<br>&gt; value is negative */
<br></blockquote><div><br></div><div><span style=3D"font-size: 13px;">It's =
covered in the negative sense:</span></div><div><span style=3D"font-size: 1=
3px;">&nbsp; &nbsp; all_nonnegative() =3D=3D !has_negative()&nbsp;</span><b=
r></div><div><span style=3D"font-size: 13px;"><br></span></div><div><span s=
tyle=3D"font-size: 13px;">For that matter, all_positive is already covered =
too:</span></div><div><span style=3D"font-size: 13px;">&nbsp; &nbsp; all_po=
sitive() =3D=3D !has_zero() &amp;&amp; !has_negative()</span><br></div><div=
><br></div><div><div><span style=3D"font-size: 13px;">I noticed three typos=
 in the quoted section:&nbsp;</span><span style=3D"font-size: 13px;">is_con=
tiguious, has_postive,&nbsp;</span><span style=3D"font-size: 13px;">all_pos=
tive</span></div></div><div><span style=3D"font-size: 13px;"><br></span></d=
iv></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_622_22744695.1389911143386--

.


Author: Tony V E <tvaneerd@gmail.com>
Date: Thu, 16 Jan 2014 17:51:30 -0500
Raw View
--001a113499a42d76ca04f01e441e
Content-Type: text/plain; charset=ISO-8859-1

On Wed, Jan 15, 2014 at 2:19 PM, Matthew Woehlke <
mw_triad@users.sourceforge.net> wrote:

> On 2014-01-15 13:34, Tony V E wrote:
>
>> On Tue, Jan 14, 2014 at 1:49 PM, Matthew Woehlke wrote:
>>
>>> In particular, I would like to get rid of any/all use of macros, for
>>>> defining the operators,  etc.
>>>>
>>>
>>> Unfortunately this is "not possible". Because the flags type is not
>>> itself
>>> the enum type, the desired binary operators taking (Enum, Flag) must be
>>> defined separately from the definition of the Flag template. So there is
>>> no
>>> way (AFAIK at least) to avoid a macro except to have to repeat this code
>>> yourself. (Which you could do if you really want to avoid the macro,
>>> but...)
>>>
>>
>> This is the basis of what I'm experimenting with:
>> [snip implementation]
>>
>
> Er... I'll omit specific comments, and just say that there is a *lot*
> missing there.
>

Obviously.  It is just a sketch of some pertinent parts.  I didn't want to
paste in the whole thing.


>
> I attached the version I'm using, with some attempt to rewrite it as an
> actual reference implementation (please pardon any style errors). I didn't
> change it to use make_unsigned as you did... I'm not sure if that's
> desirable, as it can lead to signed/unsigned mismatch because the internal
> type of the std::flags != the enum type. (Also, I added an explicit
> operator~ for the enum type which should ensure that e.g. '~enum::value'
> always has the same type as std::flags<enum>::value_t and thus won't
> trigger type conversions using as input to std::flags's operators.)


Yeah, I still need to think about the unsigned part.  In my head
operator|() is always unsigned.  Bit-wise operations on signed values is
just silly.  So I automatically made it unsigned.


>
>
>  // now here is the scary part:
>>
>> template <typename Enum>
>> typename enable_if< is_enum<Enum>::value, EnumFlags<Enum> >::type
>> operator|(Enum a, Enum b)
>> {
>>      return
>> EnumFlags<Enum>(static_cast<Enum>(static_cast<EnumFlags<
>> Enum>::value_type>(a)
>> | b));
>> }
>>
>
> Er... yes. Let's not do that. Globally defining operator| for any enum (in
> case someone has done '#include <flags>' anyway) seems dangerous.
>
>
Yeah, that's my feeling.  But I'm trying to convince myself that bitwise
operators on enums *should* promote to a different type (a type "more" than
the enum, but "less" than int). I'm at least wondering if it would be
viable for a code-base that wanted to prevent wild-west enum operations.
(ie you can also define the mixed operator|(EnumA a, EnumB b) and have it
static_assert, for example).  Obviously not OK for the standard, but might
work for some code bases.

Also, I just hate MACROS that much.

Tony

--

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

--001a113499a42d76ca04f01e441e
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><br><div class=3D"gmail=
_quote">On Wed, Jan 15, 2014 at 2:19 PM, Matthew Woehlke <span dir=3D"ltr">=
&lt;<a href=3D"mailto:mw_triad@users.sourceforge.net" target=3D"_blank">mw_=
triad@users.sourceforge.net</a>&gt;</span> wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">On 2014-01-15 13:34, Tony V E wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div class=3D"im">
On Tue, Jan 14, 2014 at 1:49 PM, Matthew Woehlke wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><blockquote class=3D"gmail_quote" style=3D"m=
argin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
In particular, I would like to get rid of any/all use of macros, for<br>
defining the operators, =A0etc.<br>
</blockquote>
<br>
Unfortunately this is &quot;not possible&quot;. Because the flags type is n=
ot itself<br>
the enum type, the desired binary operators taking (Enum, Flag) must be<br>
defined separately from the definition of the Flag template. So there is no=
<br>
way (AFAIK at least) to avoid a macro except to have to repeat this code<br=
>
yourself. (Which you could do if you really want to avoid the macro, but...=
)<br>
</blockquote>
<br>
This is the basis of what I&#39;m experimenting with:<br></div>
[snip implementation]<br>
</blockquote>
<br>
Er... I&#39;ll omit specific comments, and just say that there is a *lot* m=
issing there.<br></blockquote><div><br></div><div>Obviously.=A0 It is just =
a sketch of some pertinent parts.=A0 I didn&#39;t want to paste in the whol=
e thing.<br>
=A0<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;b=
order-left:1px #ccc solid;padding-left:1ex">
<br>
I attached the version I&#39;m using, with some attempt to rewrite it as an=
 actual reference implementation (please pardon any style errors). I didn&#=
39;t change it to use make_unsigned as you did... I&#39;m not sure if that&=
#39;s desirable, as it can lead to signed/unsigned mismatch because the int=
ernal type of the std::flags !=3D the enum type. (Also, I added an explicit=
 operator~ for the enum type which should ensure that e.g. &#39;~enum::valu=
e&#39; always has the same type as std::flags&lt;enum&gt;::value_t and thus=
 won&#39;t trigger type conversions using as input to std::flags&#39;s oper=
ators.)</blockquote>
<div><br></div><div>Yeah, I still need to think about the unsigned part.=A0=
 In my head operator|() is always unsigned.=A0 Bit-wise operations on signe=
d values is just silly.=A0 So I automatically made it unsigned.<br>=A0<br><=
/div>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div class=3D"im"><br>
<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
// now here is the scary part:<br>
<br>
template &lt;typename Enum&gt;<br>
typename enable_if&lt; is_enum&lt;Enum&gt;::value, EnumFlags&lt;Enum&gt; &g=
t;::type<br>
operator|(Enum a, Enum b)<br>
{<br>
=A0 =A0 =A0return<br>
EnumFlags&lt;Enum&gt;(static_cast&lt;<u></u>Enum&gt;(static_cast&lt;EnumFla=
gs&lt;<u></u>Enum&gt;::value_type&gt;(a)<br>
| b));<br>
}<br>
</blockquote>
<br></div>
Er... yes. Let&#39;s not do that. Globally defining operator| for any enum =
(in case someone has done &#39;#include &lt;flags&gt;&#39; anyway) seems da=
ngerous.<div class=3D"HOEnZb"><div class=3D"h5"><br></div></div></blockquot=
e>
<div><br></div><div>Yeah, that&#39;s my feeling.=A0 But I&#39;m trying to c=
onvince myself that bitwise operators on enums *should* promote to a differ=
ent type (a type &quot;more&quot; than the enum, but &quot;less&quot; than =
int). I&#39;m at least wondering if it would be viable for a code-base that=
 wanted to prevent wild-west enum operations.=A0 (ie you can also define th=
e mixed operator|(EnumA a, EnumB b) and have it static_assert, for example)=
..=A0 Obviously not OK for the standard, but might work for some code bases.=
<br>
</div><br>Also, I just hate MACROS that much.<br><br>Tony<br></div><br></di=
v></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--001a113499a42d76ca04f01e441e--

.


Author: Nevin Liber <nevin@eviloverlord.com>
Date: Thu, 16 Jan 2014 17:42:03 -0600
Raw View
--047d7bb70b2e71c58004f01efb7e
Content-Type: text/plain; charset=ISO-8859-1

On 16 January 2014 16:51, Tony V E <tvaneerd@gmail.com> wrote:

>
> Yeah, that's my feeling.  But I'm trying to convince myself that bitwise
> operators on enums *should* promote to a different type (a type "more" than
> the enum, but "less" than int).
>

I think it gets to be a bit unwieldy.  Too many types and you get
useability problems.

Then we get weird stuff like:

enum class Bits { /* ... */ };

auto b1 = Bits::Alpha;
auto b2 = Bits::Bravo | Bits::Charlie; // b2 is NOT the same type as b1

Also, what if the labels aren't distinct bits, as in:

enum class Bits
{
    Alpha = 1,
    Bravo = 2,
    Charlie = 4,

    Mask = 1 | 2 | 4,
};

If you have a "middle" type, Mask clearly belongs in it.  How do you put it
there?


In my experience, I've never seen people have a problem with the result of
combining bits from an enum back into that enum type.  My current set of
macros is:

#define ENUM(E)\
    inline constexpr std::underlying_type<E>::type operator+(E e) noexcept\
    { return static_cast<std::underlying_type<E>::type>(e); }\
    inline constexpr bool operator!(E e) noexcept\
    { return !+e; }\

#define ENUM_BITFIELD_DETAIL_BINOP(E, OP)\
    inline constexpr E operator OP (E l, E r) noexcept\
    { return static_cast<E>(+l OP +r); }\
    \
    inline E& operator OP##= (E& l, E r) noexcept\
    { return l = l OP r; }\

#define ENUM_BITFIELD(E)\
    ENUM(E)\
    ENUM_BITFIELD_DETAIL_BINOP(E, &)\
    ENUM_BITFIELD_DETAIL_BINOP(E, ^)\
    ENUM_BITFIELD_DETAIL_BINOP(E, |)\
    inline constexpr E operator~(E e) noexcept\
    { return static_cast<E>(~+e); }


--
 Nevin ":-)" Liber  <mailto:nevin@eviloverlord.com>  (847) 691-1404

--

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

--047d7bb70b2e71c58004f01efb7e
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On 16 January 2014 16:51, Tony V E <span dir=3D"ltr">&lt;<=
a href=3D"mailto:tvaneerd@gmail.com" target=3D"_blank">tvaneerd@gmail.com</=
a>&gt;</span> wrote:<br><div class=3D"gmail_extra"><div class=3D"gmail_quot=
e"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bord=
er-left:1px solid rgb(204,204,204);padding-left:1ex">

<div dir=3D"ltr"><br><div class=3D"gmail_extra"><div class=3D"gmail_quote">=
<div>Yeah, that&#39;s my feeling.=A0 But I&#39;m trying to convince myself =
that bitwise operators on enums *should* promote to a different type (a typ=
e &quot;more&quot; than the enum, but &quot;less&quot; than int).</div>

</div></div></div></blockquote><div><br></div><div>I think it gets to be a =
bit unwieldy.=A0 Too many types and you get useability problems.<br><br></d=
iv><div>Then we get weird stuff like:<br><br></div><div><font size=3D"1"><s=
pan style=3D"font-family:courier new,monospace">enum class Bits { /* ... */=
 };<br>

<br></span></font></div><div><font size=3D"1"><span style=3D"font-family:co=
urier new,monospace">auto b1 =3D Bits::Alpha;<br>auto b2 =3D Bits::Bravo | =
Bits::Charlie; // b2 is NOT the same type as b1</span></font><br><br></div>=
<div>

Also, what if the labels aren&#39;t distinct bits, as in:<br><br></div><div=
><font size=3D"1"><span style=3D"font-family:courier new,monospace">enum cl=
ass Bits<br>{<br></span></font></div><div><font size=3D"1"><span style=3D"f=
ont-family:courier new,monospace">=A0=A0=A0 Alpha =3D 1,<br>

</span></font></div><div><font size=3D"1"><span style=3D"font-family:courie=
r new,monospace">=A0=A0=A0 Bravo =3D 2,<br></span></font></div><div><font s=
ize=3D"1"><span style=3D"font-family:courier new,monospace">=A0=A0=A0 Charl=
ie =3D 4,<br><br></span></font></div>

<div><font size=3D"1"><span style=3D"font-family:courier new,monospace">=A0=
=A0=A0 Mask =3D 1 | 2 | 4,<br></span></font></div><div><font size=3D"1"><sp=
an style=3D"font-family:courier new,monospace">};</span></font><br><br></di=
v><div>If you have a &quot;middle&quot; type, <font size=3D"1"><span style=
=3D"font-family:courier new,monospace">Mask</span></font> clearly belongs i=
n it.=A0 How do you put it there?<br>

<br><br></div><div>In my experience, I&#39;ve never seen people have a prob=
lem with the result of combining bits from an enum back into that enum type=
..=A0 My current set of macros is:<br><br><font size=3D"1"><span style=3D"fo=
nt-family:courier new,monospace">#define ENUM(E)\<br>

=A0=A0=A0 inline constexpr std::underlying_type&lt;E&gt;::type operator+(E =
e) noexcept\<br>=A0=A0=A0 { return static_cast&lt;std::underlying_type&lt;E=
&gt;::type&gt;(e); }\<br>=A0=A0=A0 inline constexpr bool operator!(E e) noe=
xcept\<br>=A0=A0=A0 { return !+e; }\<br>

<br>#define ENUM_BITFIELD_DETAIL_BINOP(E, OP)\<br>=A0=A0=A0 inline constexp=
r E operator OP (E l, E r) noexcept\<br>=A0=A0=A0 { return static_cast&lt;E=
&gt;(+l OP +r); }\<br>=A0=A0=A0 \<br>=A0=A0=A0 inline E&amp; operator OP##=
=3D (E&amp; l, E r) noexcept\<br>

=A0=A0=A0 { return l =3D l OP r; }\<br><br>#define ENUM_BITFIELD(E)\<br>=A0=
=A0=A0 ENUM(E)\<br>=A0=A0=A0 ENUM_BITFIELD_DETAIL_BINOP(E, &amp;)\<br>=A0=
=A0=A0 ENUM_BITFIELD_DETAIL_BINOP(E, ^)\<br>=A0=A0=A0 ENUM_BITFIELD_DETAIL_=
BINOP(E, |)\<br>=A0=A0=A0 inline constexpr E operator~(E e) noexcept\<br>

=A0=A0=A0 { return static_cast&lt;E&gt;(~+e); }<br></span></font><br><br></=
div></div>-- <br>=A0Nevin &quot;:-)&quot; Liber=A0 &lt;mailto:<a href=3D"ma=
ilto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>&g=
t;=A0 (847) 691-1404
</div></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--047d7bb70b2e71c58004f01efb7e--

.


Author: Matthew Woehlke <mw_triad@users.sourceforge.net>
Date: Fri, 17 Jan 2014 12:27:17 -0500
Raw View
On 2014-01-16 18:42, Nevin Liber wrote:
> On 16 January 2014 16:51, Tony V E wrote:
>> Yeah, that's my feeling.  But I'm trying to convince myself that bitwise
>> operators on enums *should* promote to a different type (a type "more" than
>> the enum, but "less" than int).
>
> I think it gets to be a bit unwieldy.  Too many types and you get
> useability problems.
>
> Then we get weird stuff like:
>
> enum class Bits { /* ... */ };
>
> auto b1 = Bits::Alpha;
> auto b2 = Bits::Bravo | Bits::Charlie; // b2 is NOT the same type as b1

I don't consider this a bad thing. On the contrary, this allows
differentiating between e.g. functions that expect a single flag, and
functions that accept a set of flags.

> Also, what if the labels aren't distinct bits, as in:
>
> enum class Bits
> {
>      Alpha = 1,
>      Bravo = 2,
>      Charlie = 4,
>
>      Mask = 1 | 2 | 4,
> };
>
> If you have a "middle" type, Mask clearly belongs in it.  How do you put it
> there?

'enum class BitMasks : Bits', obviously, and then tweak the definition
of flags to also accept a 'Mask' template parameter (likely requires
that Bits automatically promotes to Bits, or else we need to definitions
of std::flags, one for Mask != Enum, and one for ==).

Since we don't have enum inheritance currently, I wasn't trying to
address that.

> In my experience, I've never seen people have a problem with the result of
> combining bits from an enum back into that enum type.  My current set of
> macros is:

....and I've never seen a problem with 'flags' being a separate type.
Obviously it isn't for Qt, and that's a fairly substantial existing
implementation.

Conversely, the idea of making a standard use case out of coercing a
value of type 'enum' (expecially 'enum class') to equal something not
actually in the enumeration just doesn't feel right to me.

--
Matthew

--

---
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: Matthew Woehlke <mw_triad@users.sourceforge.net>
Date: Fri, 17 Jan 2014 16:19:54 -0500
Raw View
This is a multi-part message in MIME format.
--------------080303090300040105050903
Content-Type: text/plain; charset=UTF-8; format=flowed

On 2014-01-15 14:19, Matthew Woehlke wrote:
> I attached the version I'm using, with some attempt to rewrite it as an
> actual reference implementation (please pardon any style errors).

Improved version, now with friend binary operators (and more overloads
for improved commutative-ness) and fix for '=0', '{0}' not working.

Unfortunately this still violates -Wzero-as-null-pointer-constant for
'expected' use. Anyone happen to know of a way to write an overload that
*only* takes a literal '0' besides nullptr_t?

--
Matthew

--

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

--------------080303090300040105050903
Content-Type: text/plain; charset=UTF-8;
 name="c++1y-std-flags.h"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="c++1y-std-flags.h"

Ly8gaGVhZGVyIGd1YXJkIGVsaWRlZAoKI2luY2x1ZGUgPHR5cGVfdHJhaXRzPgoKbmFtZXNw
YWNlIHN0ZAp7CiAgdGVtcGxhdGUgPHR5cGVuYW1lIEVudW0+IGNsYXNzIGZsYWdzCiAgewog
ICAgc3RhdGljX2Fzc2VydChzdGQ6OmlzX2VudW08RW51bT46OnZhbHVlLAogICAgICAgICAg
ICAgICAgICAic3RkOjpmbGFncyBtYXkgb25seSBiZSB1c2VkIG9uIGVudW0gdHlwZXMiKTsK
CiAgcHVibGljOgogICAgdXNpbmcgdmFsdWVfdCA9IHR5cGVuYW1lIHN0ZDo6dW5kZXJseWlu
Z190eXBlPEVudW0+Ojp0eXBlOwoKICAgIC8vIGNvbnN0cnVjdG9ycwogICAgY29uc3RleHBy
IGZsYWdzKCkgOiB2YWx1ZXswfSB7fQogICAgY29uc3RleHByIGZsYWdzKHN0ZDo6bnVsbHB0
cl90KSA6IHZhbHVlezB9IHt9CiAgICBjb25zdGV4cHIgZmxhZ3MoRW51bSBmKSA6IHZhbHVl
KHN0YXRpY19jYXN0PHZhbHVlX3Q+KGYpKSB7fQogICAgY29uc3RleHByIGZsYWdzKGZsYWdz
IGNvbnN0JikgPSBkZWZhdWx0OwoKICAgIC8vIGFzc2lnbm1lbnQKICAgIGZsYWdzJiBvcGVy
YXRvcj0oZmxhZ3MgY29uc3QmKSA9IGRlZmF1bHQ7CgogICAgZmxhZ3MmIG9wZXJhdG9yPShF
bnVtIGYpCiAgICB7IHZhbHVlID0gc3RhdGljX2Nhc3Q8dmFsdWVfdD4oZik7IHJldHVybiAq
dGhpczsgfQoKICAgIGZsYWdzJiBvcGVyYXRvcj0oc3RkOjpudWxscHRyX3QpCiAgICB7IHZh
bHVlID0gMDsgcmV0dXJuICp0aGlzOyB9CgogICAgLy8gY29udmVyc2lvbiBvcGVyYXRvcgog
ICAgY29uc3RleHByIG9wZXJhdG9yIHZhbHVlX3QoKSBjb25zdCB7IHJldHVybiB2YWx1ZTsg
fQoKICAgIC8vIGNvbXBhcmlzb24gb3BlcmF0b3JzCiAgICBjb25zdGV4cHIgZnJpZW5kIGJv
b2wgb3BlcmF0b3I9PShmbGFncyBmMSwgRW51bSBmMikKICAgIHsgcmV0dXJuIGYxLnZhbHVl
ID09IHN0YXRpY19jYXN0PHZhbHVlX3Q+KGYyKTsgfQoKICAgIGNvbnN0ZXhwciBmcmllbmQg
Ym9vbCBvcGVyYXRvcj09KEVudW0gZjEsIGZsYWdzIGYyKQogICAgeyByZXR1cm4gZjIudmFs
dWUgPT0gc3RhdGljX2Nhc3Q8dmFsdWVfdD4oZjEpOyB9CgogICAgLy8gJyYnIG9wZXJhdG9y
cwogICAgY29uc3RleHByIGZsYWdzIG9wZXJhdG9yJih2YWx1ZV90IG0pIGNvbnN0CiAgICB7
IHJldHVybiB7dmFsdWUgJiBtLCBudWxscHRyfTsgfQoKICAgIGZsYWdzJiBvcGVyYXRvciY9
KHZhbHVlX3QgbSkKICAgIHsgdmFsdWUgJj0gbTsgcmV0dXJuICp0aGlzOyB9CgogICAgY29u
c3RleHByIGZyaWVuZCBmbGFncyBvcGVyYXRvciYoZmxhZ3MgZjEsIEVudW0gZjIpCiAgICB7
IHJldHVybiB7ZjEudmFsdWUgJiBzdGF0aWNfY2FzdDx2YWx1ZV90PihmMiksIG51bGxwdHJ9
OyB9CgogICAgY29uc3RleHByIGZyaWVuZCBmbGFncyBvcGVyYXRvciYoRW51bSBmMSwgZmxh
Z3MgZjIpCiAgICB7IHJldHVybiB7ZjIudmFsdWUgJiBzdGF0aWNfY2FzdDx2YWx1ZV90Pihm
MSksIG51bGxwdHJ9OyB9CgogICAgZmxhZ3MmIG9wZXJhdG9yJj0oRW51bSBmKQogICAgeyB2
YWx1ZSAmPSBzdGF0aWNfY2FzdDx2YWx1ZV90PihmKTsgcmV0dXJuICp0aGlzOyB9CgogICAg
Ly8gJ3wnIG9wZXJhdG9ycwogICAgY29uc3RleHByIGZsYWdzIG9wZXJhdG9yfChmbGFncyBv
dGhlcikKICAgIHsgcmV0dXJuIHt2YWx1ZSB8IG90aGVyLnZhbHVlLCBudWxscHRyfTsgfQoK
ICAgIGZsYWdzJiBvcGVyYXRvcnw9KGZsYWdzIG90aGVyKQogICAgeyB2YWx1ZSB8PSBvdGhl
ci52YWx1ZTsgcmV0dXJuICp0aGlzOyB9CgogICAgY29uc3RleHByIGZyaWVuZCBmbGFncyBv
cGVyYXRvcnwoZmxhZ3MgZjEsIEVudW0gZjIpCiAgICB7IHJldHVybiB7ZjEudmFsdWUgfCBz
dGF0aWNfY2FzdDx2YWx1ZV90PihmMiksIG51bGxwdHJ9OyB9CgogICAgY29uc3RleHByIGZy
aWVuZCBmbGFncyBvcGVyYXRvcnwoRW51bSBmMSwgZmxhZ3MgZjIpCiAgICB7IHJldHVybiB7
ZjIudmFsdWUgfCBzdGF0aWNfY2FzdDx2YWx1ZV90PihmMSksIG51bGxwdHJ9OyB9CgogICAg
ZmxhZ3MmIG9wZXJhdG9yfD0oRW51bSBmKQogICAgeyB2YWx1ZSB8PSBzdGF0aWNfY2FzdDx2
YWx1ZV90PihmKTsgcmV0dXJuICp0aGlzOyB9CgogICAgLy8gJ14nIG9wZXJhdG9ycwogICAg
Y29uc3RleHByIGZsYWdzIG9wZXJhdG9yXihmbGFncyBvdGhlcikKICAgIHsgcmV0dXJuIHt2
YWx1ZSBeIG90aGVyLnZhbHVlLCBudWxscHRyfTsgfQoKICAgIGZsYWdzJiBvcGVyYXRvcl49
KGZsYWdzIG90aGVyKQogICAgeyB2YWx1ZSBePSBvdGhlci52YWx1ZTsgcmV0dXJuICp0aGlz
OyB9CgogICAgY29uc3RleHByIGZyaWVuZCBmbGFncyBvcGVyYXRvcl4oZmxhZ3MgZjEsIEVu
dW0gZjIpCiAgICB7IHJldHVybiB7ZjEudmFsdWUgXiBzdGF0aWNfY2FzdDx2YWx1ZV90Pihm
MiksIG51bGxwdHJ9OyB9CgogICAgY29uc3RleHByIGZyaWVuZCBmbGFncyBvcGVyYXRvcl4o
RW51bSBmMSwgZmxhZ3MgZjIpCiAgICB7IHJldHVybiB7ZjIudmFsdWUgXiBzdGF0aWNfY2Fz
dDx2YWx1ZV90PihmMSksIG51bGxwdHJ9OyB9CgogICAgZmxhZ3MmIG9wZXJhdG9yXj0oRW51
bSBmKQogICAgeyB2YWx1ZSBePSBzdGF0aWNfY2FzdDx2YWx1ZV90PihmKTsgcmV0dXJuICp0
aGlzOyB9CgogICAgLy8gb3RoZXIgb3BlcmF0b3JzCiAgICBjb25zdGV4cHIgdmFsdWVfdCBv
cGVyYXRvcn4oKSBjb25zdCB7IHJldHVybiB+dmFsdWU7IH0KCiAgICBjb25zdGV4cHIgYm9v
bCBvcGVyYXRvciEoKSBjb25zdCB7IHJldHVybiAhdmFsdWU7IH0KCiAgICAvLyB0ZXN0IGZs
YWcKICAgIGNvbnN0ZXhwciBib29sIHRlc3QoRW51bSBmKSBjb25zdAogICAgewogICAgICBy
ZXR1cm4gKCgqdGhpcyAmIGYpID09IGYpICYmCiAgICAgICAgICAgICAgKChzdGF0aWNfY2Fz
dDx2YWx1ZV90PihmKSAhPSAwKSB8fCAodmFsdWUgPT0gMCkpOwogICAgfQoKICAgIC8vIGNs
ZWFyIGZsYWcgLyBhbGwKICAgIHZvaWQgY2xlYXIoKSB7IHZhbHVlID0gMDsgfQogICAgdm9p
ZCBjbGVhcihFbnVtIGYpIHsgdmFsdWUgJj0gfnN0YXRpY19jYXN0PHZhbHVlX3Q+KGYpOyB9
CiAgICB2b2lkIGNsZWFyKHZhbHVlX3QgbSkgeyB2YWx1ZSAmPSB+bTsgfQoKICBwcm90ZWN0
ZWQ6CiAgICBjb25zdGV4cHIgZmxhZ3ModmFsdWVfdCB2LCBudWxscHRyX3QpIDogdmFsdWV7
dn0ge30KICAgIHZhbHVlX3QgdmFsdWU7CiAgfTsKCn0KCi8vIERlY2xhcmUganVzdCB0aGUg
b3BlcmF0b3JzIGZvciBhIGZsYWdzIHR5cGUKI2RlZmluZSBTVERfT1BFUkFUT1JTX0ZPUl9G
TEFHUyhfZW51bSkgXAogIGNvbnN0ZXhwciBpbmxpbmUgOjpzdGQ6OmZsYWdzPF9lbnVtPiBv
cGVyYXRvcnwoX2VudW0gZjEsIF9lbnVtIGYyKSBcCiAgeyByZXR1cm4gOjpzdGQ6OmZsYWdz
PF9lbnVtPntmMX0gfCBmMjsgfSBcCiAgY29uc3RleHByIGlubGluZSBhdXRvIG9wZXJhdG9y
fihfZW51bSBmKSAtPiBzdGQ6OnVuZGVybHlpbmdfdHlwZTxfZW51bT46OnR5cGUgXAogIHsg
XAogICAgc3RhdGljX2Fzc2VydChzdGQ6OmlzX2VudW08X2VudW0+Ojp2YWx1ZSwgXAogICAg
ICAgICAgICAgICAgICAiU1REX09QRVJBVE9SU19GT1JfRkxBR1MgbWF5IG9ubHkgYmUgdXNl
ZCBvbiBlbnVtIHR5cGVzIik7IFwKICAgIHJldHVybiB+c3RhdGljX2Nhc3Q8c3RkOjp1bmRl
cmx5aW5nX3R5cGU8X2VudW0+Ojp0eXBlPihmKTsgXAogIH0KCi8vIERlY2xhcmUgb3BlcmF0
b3JzIGFuZCB0eXBlIGFsaWFzIGZvciBmbGFncwojZGVmaW5lIFNURF9GTEFHUyhfZmxhZ3Ms
IF9lbnVtKSBcCiAgdXNpbmcgX2ZsYWdzID0gOjpzdGQ6OmZsYWdzPF9lbnVtPjsgXAogIFNU
RF9PUEVSQVRPUlNfRk9SX0ZMQUdTKF9lbnVtKQo=
--------------080303090300040105050903--


.


Author: Matthew Woehlke <mw_triad@users.sourceforge.net>
Date: Mon, 20 Jan 2014 12:45:25 -0500
Raw View
On 2014-01-16 17:51, Tony V E wrote:
> On Wed, Jan 15, 2014 at 2:19 PM, Matthew Woehlke wrote:
>> On 2014-01-15 13:34, Tony V E wrote:
>>> This is the basis of what I'm experimenting with:
>>> [snip implementation]
>>>
>>
>> Er... I'll omit specific comments, and just say that there is a *lot*
>> missing there.
>
> Obviously.  It is just a sketch of some pertinent parts.  I didn't want to
> paste in the whole thing.

'constexpr'?

>> I attached the version I'm using, with some attempt to rewrite it as an
>> actual reference implementation (please pardon any style errors). I didn't
>> change it to use make_unsigned as you did... I'm not sure if that's
>> desirable, as it can lead to signed/unsigned mismatch because the internal
>> type of the std::flags != the enum type. (Also, I added an explicit
>> operator~ for the enum type which should ensure that e.g. '~enum::value'
>> always has the same type as std::flags<enum>::value_t and thus won't
>> trigger type conversions using as input to std::flags's operators.)
>
>
> Yeah, I still need to think about the unsigned part.  In my head
> operator|() is always unsigned.  Bit-wise operations on signed values is
> just silly.

Why? :-)

>>>   // now here is the scary part:
>>>
>>> template <typename Enum>
>>> typename enable_if< is_enum<Enum>::value, EnumFlags<Enum> >::type
>>> operator|(Enum a, Enum b)
>>> {
>>>       return
>>> EnumFlags<Enum>(static_cast<Enum>(static_cast<EnumFlags<
>>> Enum>::value_type>(a)
>>> | b));
>>> }
>>
>> Er... yes. Let's not do that. Globally defining operator| for any enum (in
>> case someone has done '#include <flags>' anyway) seems dangerous.
>
> Yeah, that's my feeling.  But I'm trying to convince myself that bitwise
> operators on enums *should* promote to a different type (a type "more" than
> the enum, but "less" than int).

Well, your usual use case is going to be e.g.:

// declarations
STD_FLAGS(options, option)
foo(options);

// code
foo(option::A | option::B)

There's a reasonable expectation to write code like that, as opposed to:

foo(options{option::A} | option::B)

> I'm at least wondering if it would be
> viable for a code-base that wanted to prevent wild-west enum operations.
> (ie you can also define the mixed operator|(EnumA a, EnumB b) and have it
> static_assert, for example).  Obviously not OK for the standard, but might
> work for some code bases.
>
> Also, I just hate MACROS that much.

Well, sure :-). Really, though, they're not Pure Evil; sometimes they're
the best solution. I'm open to others though, as long they neither
involve making the operators available for *any* enum nor require users
to entirely define the operators themselves.

--
Matthew

--

---
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: Thiago Macieira <thiago@macieira.org>
Date: Mon, 20 Jan 2014 09:59:54 -0800
Raw View
--nextPart8094641.8ibZOvX3Ot
Content-Transfer-Encoding: 7Bit
Content-Type: text/plain; charset="us-ascii"

On segunda-feira, 20 de janeiro de 2014 12:45:25, Matthew Woehlke wrote:
> > Yeah, I still need to think about the unsigned part.  In my head
> > operator|() is always unsigned.  Bit-wise operations on signed values is
> > just silly.
>
> Why?

I'm wondering the same.

The only signed operations that might even be silly on bits (or, at least,
surprising) are right shift and sign-extension.

When talking about flags, these operations are rare, Right shift would happen
in real bitfeilds, but not in flags. Sign-extension would be problematic when
converting the full integer holding the enum / flags into a larger type, but
that can be solved by returning 32- or 64-bit integers as necessary. That way,
no sign-extension happens.

But we need to keep the signedness of the original enum, otherwise compilers
complain. See the specific issue we're trying to solve with QFlags:

https://codereview.qt-project.org/60158

--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
   Software Architect - Intel Open Source Technology Center
      PGP/GPG: 0x6EF45358; fingerprint:
      E067 918B B660 DBD1 105C  966C 33F5 F005 6EF4 5358

--nextPart8094641.8ibZOvX3Ot
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: This is a digitally signed message part.
Content-Transfer-Encoding: 7Bit

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.19 (GNU/Linux)

iD8DBQBS3WQaM/XwBW70U1gRAlnQAJsFknuae+Q9notBPpFmWiVWmas+awCfVGgN
1NIwUa1b4nI8vvYvAfAdaXs=
=wLeE
-----END PGP SIGNATURE-----

--nextPart8094641.8ibZOvX3Ot--


.


Author: Thiago Macieira <thiago@macieira.org>
Date: Mon, 20 Jan 2014 16:20:55 -0800
Raw View
On segunda-feira, 20 de janeiro de 2014 09:59:54, Thiago Macieira wrote:
> When talking about flags, these operations are rare, Right shift would
> happen  in real bitfeilds, but not in flags. Sign-extension would be
> problematic when converting the full integer holding the enum / flags into
> a larger type, but that can be solved by returning 32- or 64-bit integers
> as necessary. That way, no sign-extension happens.
>
> But we need to keep the signedness of the original enum, otherwise
> compilers  complain. See the specific issue we're trying to solve with
> QFlags:
>
> https://codereview.qt-project.org/60158

Uh... my code had the very sign-extension problem I was talking about. Fixed.
:-)

--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
   Software Architect - Intel Open Source Technology Center
      PGP/GPG: 0x6EF45358; fingerprint:
      E067 918B B660 DBD1 105C  966C 33F5 F005 6EF4 5358

--

---
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: Tony V E <tvaneerd@gmail.com>
Date: Mon, 27 Jan 2014 14:58:05 -0500
Raw View
--001a11c26b1242b3de04f0f9200d
Content-Type: text/plain; charset=ISO-8859-1

On Mon, Jan 20, 2014 at 12:59 PM, Thiago Macieira <thiago@macieira.org>wrote:

> On segunda-feira, 20 de janeiro de 2014 12:45:25, Matthew Woehlke wrote:
> > > Yeah, I still need to think about the unsigned part.  In my head
> > > operator|() is always unsigned.  Bit-wise operations on signed values
> is
> > > just silly.
> >
> > Why?
>
> I'm wondering the same.
>
>
I don't assume 2's complement representation of signed integers.  In
general, I've learned to avoid bit-twiddling signed values.  Typically it
is fine, but in my head, signed values are numbers, and unsigned values are
for bit-twiddling.  Don't mix the two.  Which also means unsigned values
are NOT for numbers.

But that's just my opinion.

Tony

--

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

--001a11c26b1242b3de04f0f9200d
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><br><div class=3D"gmail=
_quote">On Mon, Jan 20, 2014 at 12:59 PM, Thiago Macieira <span dir=3D"ltr"=
>&lt;<a href=3D"mailto:thiago@macieira.org" target=3D"_blank">thiago@maciei=
ra.org</a>&gt;</span> wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div class=3D"im">On segunda-feira, 20 de ja=
neiro de 2014 12:45:25, Matthew Woehlke wrote:<br>
&gt; &gt; Yeah, I still need to think about the unsigned part. =A0In my hea=
d<br>
&gt; &gt; operator|() is always unsigned. =A0Bit-wise operations on signed =
values is<br>
&gt; &gt; just silly.<br>
&gt;<br>
&gt; Why?<br>
<br>
</div>I&#39;m wondering the same.<br>
<br></blockquote><div><br></div><div>I don&#39;t assume 2&#39;s complement =
representation of signed integers.=A0 In general, I&#39;ve learned to avoid=
 bit-twiddling signed values.=A0 Typically it is fine, but in my head, sign=
ed values are numbers, and unsigned values are for bit-twiddling.=A0 Don&#3=
9;t mix the two.=A0 Which also means unsigned values are NOT for numbers.<b=
r>
<br>But that&#39;s just my opinion.<br><br>Tony<br><br></div></div><br></di=
v></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--001a11c26b1242b3de04f0f9200d--

.


Author: Thiago Macieira <thiago@macieira.org>
Date: Mon, 27 Jan 2014 15:53:27 -0800
Raw View
--nextPart2054646.y7jW7QTJQA
Content-Transfer-Encoding: 7Bit
Content-Type: text/plain; charset="us-ascii"

On segunda-feira, 27 de janeiro de 2014 14:58:05, Tony V E wrote:
> On Mon, Jan 20, 2014 at 12:59 PM, Thiago Macieira
<thiago@macieira.org>wrote:
> > On segunda-feira, 20 de janeiro de 2014 12:45:25, Matthew Woehlke wrote:
> > > > Yeah, I still need to think about the unsigned part.  In my head
> > > > operator|() is always unsigned.  Bit-wise operations on signed values
> >
> > is
> >
> > > > just silly.
> > >
> > > Why?
> >
> > I'm wondering the same.
>
> I don't assume 2's complement representation of signed integers.  In
> general, I've learned to avoid bit-twiddling signed values.  Typically it
> is fine, but in my head, signed values are numbers, and unsigned values are
> for bit-twiddling.  Don't mix the two.  Which also means unsigned values
> are NOT for numbers.
>
> But that's just my opinion.

I'd do what you suggested then:

template <typename Enum>
struct EnumFlags
{
    typedef typename make_unsigned<underlying_type<Enum>::type>::type
value_type;
    value_type val;
[...]

As long as only one method exists that takes an integer, the compiler will
automatically promote signed to unsigned. Probably with a warning, though.

We could advise people who do flags that they should always explicitly choose
an unsigned underlying type.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
   Software Architect - Intel Open Source Technology Center
      PGP/GPG: 0x6EF45358; fingerprint:
      E067 918B B660 DBD1 105C  966C 33F5 F005 6EF4 5358

--nextPart2054646.y7jW7QTJQA
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: This is a digitally signed message part.
Content-Transfer-Encoding: 7Bit

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.19 (GNU/Linux)

iD8DBQBS5vGKM/XwBW70U1gRAulxAJ96jpXnZKGRjhnUU+WAUI3EJ585wQCZARnZ
/793U2kjw1p5L90l9BVxgLM=
=ur3+
-----END PGP SIGNATURE-----

--nextPart2054646.y7jW7QTJQA--


.


Author: Peter Bigot <pab@pabigot.com>
Date: Mon, 27 Jan 2014 18:41:05 -0800 (PST)
Raw View
------=_Part_20_8887860.1390876865307
Content-Type: text/plain; charset=UTF-8

On Monday, January 27, 2014 5:53:27 PM UTC-6, Thiago Macieira wrote:
>
> On segunda-feira, 27 de janeiro de 2014 14:58:05, Tony V E wrote:
> > On Mon, Jan 20, 2014 at 12:59 PM, Thiago Macieira
> <thi...@macieira.org <javascript:>>wrote:
> > > On segunda-feira, 20 de janeiro de 2014 12:45:25, Matthew Woehlke
> wrote:
> > > > > Yeah, I still need to think about the unsigned part.  In my head
> > > > > operator|() is always unsigned.  Bit-wise operations on signed
> values
> > >
> > > is
> > >
> > > > > just silly.
> > > >
> > > > Why?
> > >
> > > I'm wondering the same.
> >
> > I don't assume 2's complement representation of signed integers.  In
> > general, I've learned to avoid bit-twiddling signed values.  Typically
> it
> > is fine, but in my head, signed values are numbers, and unsigned values
> are
> > for bit-twiddling.  Don't mix the two.  Which also means unsigned values
> > are NOT for numbers.
> >
> > But that's just my opinion.
>
> I'd do what you suggested then:
>
> template <typename Enum>
> struct EnumFlags
> {
>     typedef typename make_unsigned<underlying_type<Enum>::type>::type
> value_type;
>     value_type val;
> [...]
>
> As long as only one method exists that takes an integer, the compiler will
> automatically promote signed to unsigned. Probably with a warning, though.
>

> We could advise people who do flags that they should always explicitly
> choose
> an unsigned underlying type.
>

An unsigned underlying type that has the same or higher rank than int,
though, right?  Using unsigned char as the enum base could result in
integral promotion to int, reintroducing the problem of operating on signed
values.  In the general case I think you need something like this:

   using promoted_type = typename std::common_type<int,
std::underlying_type<Enum>::type>::type;
   using value_type = typename std::make_unsigned<promoted_type>::type;

Peter

--

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

<div dir=3D"ltr">On Monday, January 27, 2014 5:53:27 PM UTC-6, Thiago Macie=
ira wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:=
 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On segunda-feira, 27=
 de janeiro de 2014 14:58:05, Tony V E wrote:
<br>&gt; On Mon, Jan 20, 2014 at 12:59 PM, Thiago Macieira=20
<br>&lt;<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"=
ZIiZkbg4WQMJ" onmousedown=3D"this.href=3D'javascript:';return true;" onclic=
k=3D"this.href=3D'javascript:';return true;">thi...@macieira.org</a>&gt;wro=
te:
<br>&gt; &gt; On segunda-feira, 20 de janeiro de 2014 12:45:25, Matthew Woe=
hlke wrote:
<br>&gt; &gt; &gt; &gt; Yeah, I still need to think about the unsigned part=
.. &nbsp;In my head
<br>&gt; &gt; &gt; &gt; operator|() is always unsigned. &nbsp;Bit-wise oper=
ations on signed values
<br>&gt; &gt;=20
<br>&gt; &gt; is
<br>&gt; &gt;=20
<br>&gt; &gt; &gt; &gt; just silly.
<br>&gt; &gt; &gt;=20
<br>&gt; &gt; &gt; Why?
<br>&gt; &gt;=20
<br>&gt; &gt; I'm wondering the same.
<br>&gt;=20
<br>&gt; I don't assume 2's complement representation of signed integers. &=
nbsp;In
<br>&gt; general, I've learned to avoid bit-twiddling signed values. &nbsp;=
Typically it
<br>&gt; is fine, but in my head, signed values are numbers, and unsigned v=
alues are
<br>&gt; for bit-twiddling. &nbsp;Don't mix the two. &nbsp;Which also means=
 unsigned values
<br>&gt; are NOT for numbers.
<br>&gt;=20
<br>&gt; But that's just my opinion.
<br>
<br>I'd do what you suggested then:
<br>
<br>template &lt;typename Enum&gt;
<br>struct EnumFlags
<br>{
<br>&nbsp; &nbsp; typedef typename make_unsigned&lt;underlying_type&lt;<wbr=
>Enum&gt;::type&gt;::type
<br>value_type;
<br>&nbsp; &nbsp; value_type val;
<br>[...]
<br>
<br>As long as only one method exists that takes an integer, the compiler w=
ill=20
<br>automatically promote signed to unsigned. Probably with a warning, thou=
gh.
<br></blockquote><div></div><blockquote class=3D"gmail_quote" style=3D"marg=
in: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>We could advise people who do flags that they should always explicitly =
choose=20
<br>an unsigned underlying type.
<br></blockquote><div><br>An unsigned underlying type that has the same or =
higher rank than int, though, right?&nbsp; Using unsigned char as the enum =
base could result in integral promotion to int, reintroducing the problem o=
f operating on signed values.&nbsp; In the general case I think you need so=
mething like this:<br><br>&nbsp;&nbsp; using promoted_type =3D typename std=
::common_type&lt;int, std::underlying_type&lt;Enum&gt;::type&gt;::type;<br>=
&nbsp;&nbsp; using value_type =3D typename std::make_unsigned&lt;promoted_t=
ype&gt;::type;</div><br>Peter<br></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_20_8887860.1390876865307--

.