Topic: Reducing the need for explicit type/value disambiguation.
Author: Bengt Gustafsson <bengt.gustafsson@beamways.com>
Date: Tue, 3 Sep 2013 13:45:24 -0700 (PDT)
Raw View
------=_Part_518_21842887.1378241124792
Content-Type: text/plain; charset=ISO-8859-1
I recently asked in another subject in this group why disambiguation is
needed
so frequently. After pondering the issue some more I decided to write my
findings
down as a suggestion.
The need for 'typename' to declare in a template that a dependant name
is a type is obvious in some cases, such as when using an iterator's
value_type in an algorithm. There is no way (today at least) that the
algorithm could know that value_type is a type.
However, upon inspection of recent C++ code by myself and others it is
noticeable that these cases are in a minority compared to cases
where the compiler *could* know whether the name is a type or not. A
typical example is std::add_pointer<T>::type. To be able to use this
in a template you must of course include <type_traits> and thus the
typedef for type inside it has been seen, and this will be a type for
any T that add_pointer is instantiated for.
It should be fairly easy to add a rule that a compiler should not
require 'typename' in this case. When parsing it first sees the
(possibly qualified) name of the referred template (such as
std::add_pointer) then it sees its own template parameter (or
something else known to be a type, or disambiguated to be one) and
finally the name of a member of the referred template. No parsing
problems in sight...
Specialization could be a problem, depending on how the code is
written. For instance enable_if<bool, T>::type only contains the
typedef type if the first parameter is true. With my suggestion
this would only work if the base case was for true like this:
template <bool b, typename T = void> struct enable_if {
typedef T type;
};
template<typename T> struct enable_if<false, T> {
};
and not if it was done the other way around. cppreference.com lists
the opposite variant as a "possible implementation", but the code
above would work the same and is thus also a "possible
implementation".
In this particular type of case having the compiler inspect also
specializations would improve the situation so that the
cppreference.com code would work too. In general this however does not
solve the problem as the specialization for a particular T may well be below
the place of use in the referring template. Therefore I would not
suggest that specializations are to be inspected.
The result will be that if the code above is in the standard headers
the typename before enable_if would not be required, but with the
opposite code it would. Thus for portability reasons the standard
would have to be augmented with a demand that the base case must be
the version that includes the typedef. On the other hand I don't think
there are any other templates with this behaviour besides enable_if, as
its sole purpose is to conditionally "work" or not depending on the
bool value. For other standard templates not defining type for some
parameters would not be logical. [I'm not positive on this, please
help me with other problem cases, if any].
Within user code the need for a typename disambiguation would depend on
whether the dependant type is in the base template or not. This
should not be a big deal, cunning programmes would place the type
declaration in the base case and others would add 'typename' as
directed by the compiler. As the user compiles the same code there is no
portability issue.
When the referred template is itself a template template parameter
this rule would not be applicable as there is no particular class
template to inspect, this is unknown at the time of compilation,
and thus 'typename' would be required.
*Relation to constraints/concepts:
*
In the initially mentioned case of Iterator::value_type constraints or at
least
concepts could reduce the need for 'typename', but this happens in quite
different situations than those handled by this suggestion. Here is a
discussion
around this (a little bit off topic):
With constraints (concepts-lite) it would be almost impossible to
know that e.g. Iterator denoted template parameters have a nested
typedef called value_type as it is buried inside a predicate in the
constexpr
function named Iterator. While it would theoretically be possible
for the compiler to decipher the bool expression therein I doubt that
the standard committee will find it feasible to demand this from
compiler vendors. It sort of defies the 'lite' in the name...
With a more full concept implementation a description of the template
parameter would be available and the existence of a type called
value_type should quite easily be deducible by the compiler, and thus
disambiguation would be possible to skip.
--
---
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_518_21842887.1378241124792
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I recently asked in another subject in this group why disa=
mbiguation is needed<div>so frequently. After pondering the issue some more=
I decided to write my findings</div><div>down as a suggestion.<div><br></d=
iv><div><div>The need for 'typename' to declare in a template that a depend=
ant name</div><div>is a type is obvious in some cases, such as when using a=
n iterator's</div><div>value_type in an algorithm. There is no way (today a=
t least) that the</div><div>algorithm could know that value_type is a type.=
</div><div><br></div><div>However, upon inspection of recent C++ code by my=
self and others it is</div><div>noticeable that these cases are in a minori=
ty compared to cases</div><div>where the compiler <i>could</i> know whether=
the name is a type or not. A</div><div>typical example is std::add_pointer=
<T>::type. To be able to use this</div><div>in a template you must of=
course include <type_traits> and thus the</div><div>typedef for type=
inside it has been seen, and this will be a type for</div><div>any T that =
add_pointer is instantiated for.</div><div><br></div><div>It should be fair=
ly easy to add a rule that a compiler should not</div><div>require 'typenam=
e' in this case. When parsing it first sees the</div><div>(possibly qualifi=
ed) name of the referred template (such as</div><div>std::add_pointer) then=
it sees its own template parameter (or</div><div>something else known to b=
e a type, or disambiguated to be one) and</div><div>finally the name of a m=
ember of the referred template. No parsing</div><div>problems in sight...</=
div><div><br></div><div>Specialization could be a problem, depending on how=
the code is</div><div>written. For instance enable_if<bool, T>::type=
only contains the</div><div>typedef type if the first parameter is true. W=
ith my suggestion</div><div>this would only work if the base case was for t=
rue like this:</div><div><br></div><div>template <bool b, typename T =3D=
void> struct enable_if {</div><div> typedef T type;</div><=
div>};</div><div><br></div><div>template<typename T> struct enable_if=
<false, T> {</div><div>};</div><div><br></div><div>and not if it was =
done the other way around. cppreference.com lists</div><div>the opposite va=
riant as a "possible implementation", but the code</div><div>above would wo=
rk the same and is thus also a "possible</div><div>implementation".</div><d=
iv><br></div><div>In this particular type of case having the compiler inspe=
ct also</div><div>specializations would improve the situation so that the</=
div><div>cppreference.com code would work too. In general this however does=
not</div><div>solve the problem as the specialization for a particular T m=
ay well be below</div><div>the place of use in the referring template. Ther=
efore I would not</div><div>suggest that specializations are to be inspecte=
d.</div><div><br></div><div>The result will be that if the code above is in=
the standard headers</div><div>the typename before enable_if would not be =
required, but with the</div><div>opposite code it would. Thus for portabili=
ty reasons the standard</div><div>would have to be augmented with a demand =
that the base case must be</div><div>the version that includes the typedef.=
On the other hand I don't think</div><div>there are any other templates wi=
th this behaviour besides enable_if, as</div><div>its sole purpose is to co=
nditionally "work" or not depending on the</div><div>bool value. For other =
standard templates not defining type for some</div><div>parameters would no=
t be logical. [I'm not positive on this, please</div><div>help me with othe=
r problem cases, if any].</div><div><br></div><div>Within user code the nee=
d for a typename disambiguation would depend on</div><div>whether the depen=
dant type is in the base template or not. This</div><div>should not be a bi=
g deal, cunning programmes would place the type</div><div>declaration in th=
e base case and others would add 'typename' as</div><div>directed by the co=
mpiler. As the user compiles the same code there is no portability issue.</=
div><div><br></div><div>When the referred template <span style=3D"font=
-size: 13px;">is</span><span style=3D"font-size: 13px;"> </span><span =
style=3D"font-size: 13px;">itself a template template parameter</span></div=
><div>this rule would not be applicable as there is no particular class</di=
v><div>template to inspect, this is unknown at the time of compilation,</di=
v><div>and thus 'typename' would be required.</div><div><span style=3D"font=
-size: 13px;"><br></span></div><div><b><span style=3D"font-size: 13px;">Rel=
ation to constraints/concepts:</span><br></b></div><div><br></div><div>In t=
he initially mentioned case of Iterator::value_type constraints or at least=
</div><div>concepts could reduce <span style=3D"font-size: 13px;">the =
need for 'typename', but this happens in quite</span></div><div><span style=
=3D"font-size: 13px;">different situations than those handled by this sugge=
stion. Here is a discussion</span></div><div><span style=3D"font-size: 13px=
;">around this (a little bit off topic):</span></div><div><br></div><div>Wi=
th constraints (concepts-lite) it would be almost impossible to</div><div>k=
now that e.g. Iterator denoted template parameters have a nested</div><div>=
typedef called value_type as it is buried inside a predicate in the constex=
pr</div><div>function named Iterator. While it would theoretically be=
possible</div><div>for the compiler to decipher the bool expression therei=
n I doubt that</div><div>the standard committee will find it feasible to de=
mand this from</div><div>compiler vendors. It sort of defies the 'lite' in =
the name...</div><div><br></div><div>With a more full concept implementatio=
n a description of the template</div><div>parameter would be available and =
the existence of a type called</div><div>value_type should quite easily be =
deducible by the compiler, and thus</div><div>disambiguation would be possi=
ble to skip.</div><div><br></div><div><br></div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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_518_21842887.1378241124792--
.
Author: David Krauss <potswa@gmail.com>
Date: Tue, 3 Sep 2013 17:36:48 -0700 (PDT)
Raw View
------=_Part_3962_4117678.1378255008759
Content-Type: text/plain; charset=ISO-8859-1
Agreed completely. I had a related idea:
https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/mRcG3v02nJg
..
Not only is typename disambiguation redundant, but "members of an unknown
specialization", i.e. of a type-dependent base class, should be available
with unqualified names.
What needs to be proposed is a set of rules for translating concept
requirements into implicit declarations.
--
---
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_3962_4117678.1378255008759
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Agreed completely. I had a related idea: https://groups.go=
ogle.com/a/isocpp.org/forum/#!topic/std-proposals/mRcG3v02nJg .<br><br>Not =
only is <span style=3D"font-family: courier new,monospace;">typename</span>=
disambiguation redundant, but "members of an unknown specialization", i.e.=
of a type-dependent base class, should be available with unqualified names=
..<br><br>What needs to be proposed is a set of rules for translating concep=
t requirements into implicit declarations.<br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_3962_4117678.1378255008759--
.
Author: cornedbee@google.com
Date: Wed, 4 Sep 2013 06:23:03 -0700 (PDT)
Raw View
------=_Part_3269_13393679.1378300983459
Content-Type: text/plain; charset=ISO-8859-1
On Tuesday, September 3, 2013 10:45:24 PM UTC+2, Bengt Gustafsson wrote:
>
> I recently asked in another subject in this group why disambiguation is
> needed
> so frequently. After pondering the issue some more I decided to write my
> findings
> down as a suggestion.
>
> The need for 'typename' to declare in a template that a dependant name
> is a type is obvious in some cases, such as when using an iterator's
> value_type in an algorithm. There is no way (today at least) that the
> algorithm could know that value_type is a type.
>
An algorithm isn't supposed to use Iterator::value_type, it's supposed to
use std::iterator_traits<Iterator>::value_type. Which makes this case
equivalent to the one below, because the base definition of iterator_traits
is
template <typename It>
struct iterator_traits {
typedef typename It::value_type value_type;
// ...
};
>
> However, upon inspection of recent C++ code by myself and others it is
> noticeable that these cases are in a minority compared to cases
> where the compiler *could* know whether the name is a type or not. A
> typical example is std::add_pointer<T>::type. To be able to use this
> in a template you must of course include <type_traits> and thus the
> typedef for type inside it has been seen, and this will be a type for
> any T that add_pointer is instantiated for.
>
The only thing stopping me from doing the nasty thing:
namespace std {
template <typename T>
struct add_pointer<T&&> {
constexpr bool type = false; // muahahahaha!
};
}
is that the library specification (not the core language) says that adding
specializations is undefined behavior. That might protect the standard
library, but not other libraries.
> It should be fairly easy to add a rule that a compiler should not
> require 'typename' in this case.
>
OK, let's see what this entails.
First, define "this case": "A qualified name that refers to a member of an
instantiation of a known template, even if the actual arguments to the
template are not yet known, is parsed as a type name if looking up the name
in the primary template finds a type. If actual instantiation of the
template resolves to a specialization where the name does not exist or is
not a type, the program is ill-formed."
That wasn't too bad. Not nice, but not horrible either. So we can specify
it. (Make sure that templates nested in templates don't make this way more
complicated.) But that's not the only criterion: we also need to implement
and teach it. We might want to check backward compatibility. So let's look
at that.
There are two main ways templates are handled by compilers. One way parses
the template into an AST with the template parameters incorporated.
Instantiation means substituting the template arguments into the AST to
yield a new AST that isn't a template (or might still be, if it is a nested
template). The other way just caches the tokens of the template without
analyzing it. Instantiation means actually parsing the cached tokens, with
template parameters replaced by their arguments.
For the first model, implementing this means doing name lookup in the AST
for the primary template. This should be possible. Note, however, that this
model *requires* the last part of my specification above. In current
implementations, the AST, once built, cannot be changed to accommodate a
name that was previously assumed to be a type suddenly becoming a value, or
vice versa. Making this possible would be very, very hard.
The second model doesn't really need typename disambiguation in the first
place, since it only ever parses code with the template parameters
substituted. However, correctly diagnosing the absence of a required
typename would be tricky: when actual instantiation happens to be in a
specialization, the compiler then has to also parse the primary template,
except that it has to do this in a lenient, error-ignoring mode because the
primary template was never meant to be instantiated with that particular
type. (Try, for example, substituting int* into the primary iterator_traits
template.) So while this is possible, it's far from trivial.
I suppose this is implementable.
Teaching. First, from a template user's perspective.
The C++03 rule was, "Put typename in front of names nested in something
dependent, except in situations where a type is unambiguously required,
such as base classes, and never put it anywhere else." This depends on the
notion of dependent names, which is tricky.
C++11 relaxed this, allowing typename in other places too. The new rule is
the same as the C++03, except for the last part, which now says, "and you
can also put it in front of any other qualified name if you want to, so
when in doubt, use typename." This helps a little, since the user isn't
punished as hard for not knowing exactly when a name is dependent. It also
allows simpler rules, such as "Use typename when you refer to a type in a
template or template parameter." You still can't put typename in front of
base class names, though.
With your idea, the rule becomes, 'Put typename in front of names nested in
something dependent, unless that something is a known template with unknown
parameters and the primary template contains a type with that name, and
except in situations where a type is unambiguously required." This is not
actually simpler! This is harder! Now, in addition to dependent names, we
have primary templates. Worse, previously the rule was completely decidable
based on local code: did you use template parameters in there somewhere?
Use typename. Now that isn't enough if you want to minimize usage of
typename: to know whether you can omit it, you have to look at the template
you're using to find out whether the primary template has already has the
type, or whether it's only a specialization that does. That's not a good
thing.
So teaching this to a template user actually becomes harder. Now look at
the other side: we suddenly have new rules for people who write templates.
"If you want to allow usage of that nested type without typename, make sure
it's in the primary template."
This isn't a hard rule. It's just a new rule where there was none before.
And it's not always trivial. Look, for example, at this naive
implementation of tuple_element.
template <unsigned I, typename... Types> struct pack_element; // This is
the primary template. It doesn't even have a body!
template <typename T, typename... Rest> struct pack_element<0, T, Rest...>
{ using type = T; };
template <unsigned I, typename T, typename... Rest> struct pack_element<I,
T, Rest...> : pack_element<I-1, Rest...> {};
template <typename Tuple, unsigned I> struct tuple_element; // This is the
primary template. It doesn't even have a body!
template <typename... Types, unsigned I> struct
tuple_element<tuple<Types...>, I> : pack_element<I, Types...> {};
When passed an invalid index or something other than a tuple, these will
automatically fail, because they try to instantiate an undefined template.
But to take advantage of your rule, I now have to do this:
template <unsigned I, typename... Types> struct pack_element {
using type = void;
static_assert(false, "Index out of bounds.");
};
template <typename Tuple, unsigned I struct tuple_element {
using type = void;
static_assert(false, "Argument is not a tuple.");
};
Arguably I should do the static_asserts anyway, if only for the improved
error messages, but now I need that weird type alias in there too. Yes,
that's weird.
Not too bad, but it does make things more complicated.
But here's a really annoying case. Suppose I don't like the way
std::enable_if works. I want the syntax my::static_if<condition>::enable
and my::static_if<condition>::disable. Here's how I would write this:
template <bool Cond, typename T = void> struct static_if { using enable =
T; };
template <typename T> struct static_if<false, T> { using disable = T; };
Suddenly, enable can be used without typename, disable can't. The simple
"swap the cases" suggestion that worked for enable_if doesn't work here.
Instead I have to add a primary template with both types:
template <bool Cond, typename T = void> struct static_if { using enable =
T; using disable = T; } // will never be instantiated
template <typename T> struct static_if<false, T> { using disable = T; };
template <typename T> struct static_if<true, T> { using enable = T; };
Well, that's more than 50% increase in size for that template. Just
throwing this out there.
Backwards compatibility. Clearly, there is theoretical code that will break
with the new rule, e.g.
template <typename T> struct thing { using thing = T; };
template <typename T> struct thing<T*> { T* thing(int, int); };
template <typename T>
void fn(int i, int j) {
auto x = foobar<T*>::thing(i, j); // Valid code, but illegal under the
new rule, because thing was assumed to be a type.
};
Is this code reasonable? This example really isn't, but that doesn't mean
there aren't reasonable versions of something like it. But does such code
exist anyway? Not sure - template metaprograms may contain hidden instances
of something like this, but it would take a major code survey to find out.
These are the challenges to be overcome. And the advantages of your
feature? It does not make C++ simpler (there are still cases where typename
is needed, and the rule to decide when got more complicated, not less). All
it does is save you 9 keystrokes every time you refer to a dependent nested
name that should be a type.
It may be just me, but I don't think that's worth it.
--
---
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_3269_13393679.1378300983459
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Tuesday, September 3, 2013 10:45:24 PM UTC+2, B=
engt Gustafsson 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">I recently asked in another subject in this group why disambiguati=
on is needed<div>so frequently. After pondering the issue some more I decid=
ed to write my findings</div><div>down as a suggestion.<div><br></div><div>=
<div>The need for 'typename' to declare in a template that a dependant name=
</div><div>is a type is obvious in some cases, such as when using an iterat=
or's</div><div>value_type in an algorithm. There is no way (today at least)=
that the</div><div>algorithm could know that value_type is a type.</div></=
div></div></div></blockquote><div><br></div><div>An algorithm isn't suppose=
d to use Iterator::value_type, it's supposed to use std::iterator_traits<=
;Iterator>::value_type. Which makes this case equivalent to the one belo=
w, because the base definition of iterator_traits is</div><div><br></div><d=
iv>template <typename It></div><div>struct iterator_traits {</div><di=
v> typedef typename It::value_type value_type;</div><div> // ..=
..</div><div>};</div><div> </div><blockquote class=3D"gmail_quote" styl=
e=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left:=
1ex;"><div dir=3D"ltr"><div><div><div><br></div><div>However, upon inspect=
ion of recent C++ code by myself and others it is</div><div>noticeable that=
these cases are in a minority compared to cases</div><div>where the compil=
er <i>could</i> know whether the name is a type or not. A</div><div>typical=
example is std::add_pointer<T>::type. To be able to use this</div><d=
iv>in a template you must of course include <type_traits> and thus th=
e</div><div>typedef for type inside it has been seen, and this will be a ty=
pe for</div><div>any T that add_pointer is instantiated for.</div></div></d=
iv></div></blockquote><div><br></div><div>The only thing stopping me from d=
oing the nasty thing:</div><div><br></div><div>namespace std {</div><div>te=
mplate <typename T></div><div>struct add_pointer<T&&> {=
</div><div> constexpr bool type =3D false; // muahahahaha!</div><div>=
};</div><div>}</div><div><br></div><div>is that the library specification (=
not the core language) says that adding specializations is undefined behavi=
or. That might protect the standard library, but not other libraries.</div>=
<div><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-=
left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr=
"><div><div><div><br></div><div>It should be fairly easy to add a rule that=
a compiler should not</div><div>require 'typename' in this case.</div></di=
v></div></div></blockquote><div><br></div><div>OK, let's see what this enta=
ils.</div><div><br></div><div>First, define "this case": "A qualified name =
that refers to a member of an instantiation of a known template, even if th=
e actual arguments to the template are not yet known, is parsed as a type n=
ame if looking up the name in the primary template finds a type. If actual =
instantiation of the template resolves to a specialization where the name d=
oes not exist or is not a type, the program is ill-formed."</div><div><br><=
/div><div>That wasn't too bad. Not nice, but not horrible either. So we can=
specify it. (Make sure that templates nested in templates don't make this =
way more complicated.) But that's not the only criterion: we also need to i=
mplement and teach it. We might want to check backward compatibility. So le=
t's look at that.</div><div><br></div><div>There are two main ways template=
s are handled by compilers. One way parses the template into an AST with th=
e template parameters incorporated. Instantiation means substituting the te=
mplate arguments into the AST to yield a new AST that isn't a template (or =
might still be, if it is a nested template). The other way just caches the =
tokens of the template without analyzing it. Instantiation means actually p=
arsing the cached tokens, with template parameters replaced by their argume=
nts.</div><div><br></div><div>For the first model, implementing this means =
doing name lookup in the AST for the primary template. This should be possi=
ble. Note, however, that this model *requires* the last part of my specific=
ation above. In current implementations, the AST, once built, cannot be cha=
nged to accommodate a name that was previously assumed to be a type suddenl=
y becoming a value, or vice versa. Making this possible would be very, very=
hard.</div><div><br></div><div>The second model doesn't really need typena=
me disambiguation in the first place, since it only ever parses code with t=
he template parameters substituted. However, correctly diagnosing the absen=
ce of a required typename would be tricky: when actual instantiation happen=
s to be in a specialization, the compiler then has to also parse the primar=
y template, except that it has to do this in a lenient, error-ignoring mode=
because the primary template was never meant to be instantiated with that =
particular type. (Try, for example, substituting int* into the primary iter=
ator_traits template.) So while this is possible, it's far from trivial.</d=
iv><div><br></div><div>I suppose this is implementable.</div><div><br></div=
><div>Teaching. First, from a template user's perspective.</div><div><br></=
div><div>The C++03 rule was, "Put typename in front of names nested in some=
thing dependent, except in situations where a type is unambiguously require=
d, such as base classes, and never put it anywhere else." This depends on t=
he notion of dependent names, which is tricky.</div><div><br></div><div>C++=
11 relaxed this, allowing typename in other places too. The new rule is the=
same as the C++03, except for the last part, which now says, "and you can =
also put it in front of any other qualified name if you want to, so when in=
doubt, use typename." This helps a little, since the user isn't punished a=
s hard for not knowing exactly when a name is dependent. It also allows sim=
pler rules, such as "Use typename when you refer to a type in a template or=
template parameter." You still can't put typename in front of base class n=
ames, though.</div><div><br></div><div>With your idea, the rule becomes, 'P=
ut typename in front of names nested in something dependent, unless that so=
mething is a known template with unknown parameters and the primary templat=
e contains a type with that name, and except in situations where a type is =
unambiguously required." This is not actually simpler! This is harder! Now,=
in addition to dependent names, we have primary templates. Worse, previous=
ly the rule was completely decidable based on local code: did you use templ=
ate parameters in there somewhere? Use typename. Now that isn't enough if y=
ou want to minimize usage of typename: to know whether you can omit it, you=
have to look at the template you're using to find out whether the primary =
template has already has the type, or whether it's only a specialization th=
at does. That's not a good thing.</div><div><br></div><div>So teaching this=
to a template user actually becomes harder. Now look at the other side: we=
suddenly have new rules for people who write templates.</div><div><br></di=
v><div>"If you want to allow usage of that nested type without typename, ma=
ke sure it's in the primary template."</div><div><br></div><div>This isn't =
a hard rule. It's just a new rule where there was none before. And it's not=
always trivial. Look, for example, at this naive implementation of tuple_e=
lement.</div><div><br></div><div>template <unsigned I, typename... Types=
> struct pack_element; // This is the primary template. It doesn't even =
have a body!</div><div>template <typename T, typename... Rest> struct=
pack_element<0, T, Rest...> { using type =3D T; };</div><div>templat=
e <unsigned I, typename T, typename... Rest> struct pack_element<I=
, T, Rest...> : pack_element<I-1, Rest...> {};</div><div><br></div=
><div>template <typename Tuple, unsigned I> struct tuple_element; // =
This is the primary template. It doesn't even have a body!</div><div>templa=
te <typename... Types, unsigned I> struct tuple_element<tuple<T=
ypes...>, I> : pack_element<I, Types...> {};</div><div><br></di=
v><div>When passed an invalid index or something other than a tuple, these =
will automatically fail, because they try to instantiate an undefined templ=
ate. But to take advantage of your rule, I now have to do this:</div><div><=
br></div><div>template <unsigned I, typename... Types> struct pack_el=
ement {</div><div> using type =3D void;</div><div> static_asser=
t(false, "Index out of bounds.");</div><div>};</div><div><br></div><div>tem=
plate <typename Tuple, unsigned I struct tuple_element {</div><div> =
; using type =3D void;</div><div> static_assert(false, "Argument is n=
ot a tuple.");</div><div>};</div><div><br></div><div>Arguably I should do t=
he static_asserts anyway, if only for the improved error messages, but now =
I need that weird type alias in there too. Yes, that's weird.</div><div><br=
></div><div>Not too bad, but it does make things more complicated.</div><di=
v><br></div><div>But here's a really annoying case. Suppose I don't like th=
e way std::enable_if works. I want the syntax my::static_if<condition>=
;::enable and my::static_if<condition>::disable. Here's how I would w=
rite this:</div><div><br></div><div>template <bool Cond, typename T =3D =
void> struct static_if { using enable =3D T; };</div><div>template <t=
ypename T> struct static_if<false, T> { using disable =3D T; };</d=
iv><div><br></div><div>Suddenly, enable can be used without typename, disab=
le can't. The simple "swap the cases" suggestion that worked for enable_if =
doesn't work here. Instead I have to add a primary template with both types=
:</div><div><br></div><div>template <bool Cond, typename T =3D void> =
struct static_if { using enable =3D T; using disable =3D T; } // will never=
be instantiated</div><div>template <typename T> struct static_if<=
false, T> { using disable =3D T; };</div><div>template <typename T>=
; struct static_if<true, T> { using enable =3D T; };</div><div><br></=
div><div>Well, that's more than 50% increase in size for that template. Jus=
t throwing this out there.</div><div><br></div><div>Backwards compatibility=
.. Clearly, there is theoretical code that will break with the new rule, e.g=
..</div><div><br></div><div>template <typename T> struct thing { using=
thing =3D T; };</div><div>template <typename T> struct thing<T*&g=
t; { T* thing(int, int); };</div><div><br></div><div>template <typename =
T></div><div>void fn(int i, int j) {</div><div> auto x =3D foobar&=
lt;T*>::thing(i, j); // Valid code, but illegal under the new rule, beca=
use thing was assumed to be a type.</div><div>};</div><div><br></div><div>I=
s this code reasonable? This example really isn't, but that doesn't mean th=
ere aren't reasonable versions of something like it. But does such code exi=
st anyway? Not sure - template metaprograms may contain hidden instances of=
something like this, but it would take a major code survey to find out.</d=
iv><div><br></div><div>These are the challenges to be overcome. And the adv=
antages of your feature? It does not make C++ simpler (there are still case=
s where typename is needed, and the rule to decide when got more complicate=
d, not less). All it does is save you 9 keystrokes every time you refer to =
a dependent nested name that should be a type.</div><div><br></div><div>It =
may be just me, but I don't think that's worth it.</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_3269_13393679.1378300983459--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Wed, 4 Sep 2013 09:45:26 -0500
Raw View
--047d7b5daca08a6bb604e58fddc5
Content-Type: text/plain; charset=ISO-8859-1
On 4 September 2013 08:23, <cornedbee@google.com> wrote:
> It may be just me, but I don't think that's worth it.
+1
It's not just you...
--
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/.
--047d7b5daca08a6bb604e58fddc5
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><br><div class=3D"gmail_quote">=
On 4 September 2013 08:23, <span dir=3D"ltr"><<a href=3D"mailto:cornedb=
ee@google.com" target=3D"_blank">cornedbee@google.com</a>></span> wrote:=
<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-lef=
t:1px #ccc solid;padding-left:1ex">
It may be just me, but I don't think that's worth it.</blockquote><=
div>=A0</div></div>+1 <br><br></div><div class=3D"gmail_extra">It's not=
just you...<br>-- <br>=A0Nevin ":-)" Liber=A0 <mailto:<a href=
=3D"mailto:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com=
</a>>=A0 (847) 691-1404
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7b5daca08a6bb604e58fddc5--
.
Author: cornedbee@google.com
Date: Thu, 5 Sep 2013 04:31:34 -0700 (PDT)
Raw View
------=_Part_3840_1175423.1378380694691
Content-Type: text/plain; charset=ISO-8859-1
On Wednesday, September 4, 2013 3:23:03 PM UTC+2, corn...@google.com wrote:
>
>
> Backwards compatibility. Clearly, there is theoretical code that will
> break with the new rule, e.g.
>
> template <typename T> struct thing { using thing = T; };
> template <typename T> struct thing<T*> { T* thing(int, int); };
>
The struct template was of course meant to be called 'foobar'.
>
> template <typename T>
> void fn(int i, int j) {
> auto x = foobar<T*>::thing(i, j); // Valid code, but illegal under the
> new rule, because thing was assumed to be a type.
> };
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_3840_1175423.1378380694691
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Wednesday, September 4, 2013 3:23:03 PM UTC+2, =
corn...@google.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"><br><div>Backwards compatibility. Clearly, there is theoretical=
code that will break with the new rule, e.g.</div><div><br></div><div>temp=
late <typename T> struct thing { using thing =3D T; };</div><div>temp=
late <typename T> struct thing<T*> { T* thing(int, int); };</di=
v></div></blockquote><div><br></div><div>The struct template was of course =
meant to be called 'foobar'.</div><div> </div><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"><div><br></div><div>template <type=
name T></div><div>void fn(int i, int j) {</div><div> auto x =3D fo=
obar<T*>::thing(i, j); // Valid code, but illegal under the new rule,=
because thing was assumed to be a type.</div><div>};</div></div></blockquo=
te><div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_3840_1175423.1378380694691--
.
Author: Bengt Gustafsson <bengt.gustafsson@beamways.com>
Date: Thu, 5 Sep 2013 15:02:18 -0700 (PDT)
Raw View
------=_Part_4194_8773529.1378418538348
Content-Type: text/plain; charset=ISO-8859-1
Well, my initial motivation for this suggestion was actually to simplify
teaching, as it is quite hard for people to understand that even though the
compiler has seen that add_const<T>::type is a type it chooses to ignore
this fact... In contrast it is very easy to understand that T::value_type
can't be known to be a type. I don't think that a rule that has fewer words
is always easier to learn, if it doesn't seem logical. In this case the new
tutorial text would be "put a typename in if the compiler doesn't know if
the dependant name is a type [from looking at the main template]". I don't
think that the last part of the sentence is needed, even. It would only be
interesting if someone came up with your code-breaking idea.
Your breaking code is indisputable of course, but I don't know if anybody
has really a good use case for changing from type to function in a
specialization. In your particular example it would be possible to know
that the code is valid, but I admit that I was really hoping not to have to
inspect specializations, this makes the implementation problem much worse. But
if the committee finds that it is ok to break all code that has a "using
namespace std" and has a class called Object (which I hope they don't), I
would say that "specialize a class template so that a name of a type is a
function/member" is a worse breakage of coding discipline, much less
commonoly occurring and easier to fix and should thus be more acceptable.
On the other hand, as we can now write:
template<typename T> using add_const = const T;
and then add_const<T> without both the leading typename and the trailing
::type I think that the use for this suggestion is diminished from the code
clutter standpoint. Now, if we could only find a way to get rid of the _t
on the names of the usings for new code, I would be quite happy...
Den torsdagen den 5:e september 2013 kl. 13:31:34 UTC+2 skrev
corn...@google.com:
>
>
>
> On Wednesday, September 4, 2013 3:23:03 PM UTC+2, corn...@google.comwrote:
>>
>>
>> Backwards compatibility. Clearly, there is theoretical code that will
>> break with the new rule, e.g.
>>
>> template <typename T> struct thing { using thing = T; };
>> template <typename T> struct thing<T*> { T* thing(int, int); };
>>
>
> The struct template was of course meant to be called 'foobar'.
>
>
>>
>> template <typename T>
>> void fn(int i, int j) {
>> auto x = foobar<T*>::thing(i, j); // Valid code, but illegal under the
>> new rule, because thing was assumed to be a type.
>> };
>>
>
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_4194_8773529.1378418538348
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Well, my initial motivation for this suggestion was actual=
ly to simplify teaching, as it is quite hard for people to understand that =
even though the compiler has seen that add_const<T>::type is a type i=
t chooses to ignore this fact... In contrast it is very easy to understand =
that T::value_type can't be known to be a type. I don't think that a rule t=
hat has fewer words is always easier to learn, if it doesn't seem logical. =
In this case the new tutorial text would be "put a typename in if the compi=
ler doesn't know if the dependant name is a type [from looking at the main =
template]". I don't think that the last part of the sentence is needed, eve=
n. It would only be interesting if someone came up with your code-breaking =
idea.<div><br></div><div><span style=3D"font-size: 13px;">Your breaking cod=
e is indisputable of course, but I don't know if anybody has really a good =
use case for changing from type to function in a specialization. </spa=
n><span style=3D"font-size: 13px;"> </span><span style=3D"font-size: 1=
3px;">In your particular example it would be possible to know that the code=
is valid, but I admit that I was really hoping not to have to inspect spec=
ializations, this makes the implementation problem much worse.</span><span =
style=3D"font-size: 13px;"> But if the committee finds that it is ok t=
o break all code that has a "using namespace std" and has a class called Ob=
ject (which I hope they don't), I would say that "specialize a class templa=
te so that a name of a type is a function/member" is a worse breakage of co=
ding discipline, much less commonoly occurring and easier to fix and should=
thus be more acceptable.</span></div><div><span style=3D"font-size: 13px;"=
><br></span></div><div><span style=3D"font-size: 13px;">On the other hand, =
as we can now write:</span><br></div><div><span style=3D"font-size: 13px;">=
<br></span></div><div>template<typename T> using add_const =3D const =
T;</div><div><br></div><div>and then add_const<T> without both the le=
ading typename and the trailing ::type I think that the use for this sugges=
tion is diminished from the code clutter standpoint. Now, if we could only =
find a way to get rid of the _t on the names of the usings for new code, I =
would be quite happy...</div><div><br></div><div><br>Den torsdagen den 5:e =
september 2013 kl. 13:31:34 UTC+2 skrev corn...@google.com:<blockquote clas=
s=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #c=
cc solid;padding-left: 1ex;"><div dir=3D"ltr"><br><br>On Wednesday, Septemb=
er 4, 2013 3:23:03 PM UTC+2, <a>corn...@google.com</a> wrote:<blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #cc=
c solid;padding-left:1ex"><div dir=3D"ltr"><br><div>Backwards compatibility=
.. Clearly, there is theoretical code that will break with the new rule, e.g=
..</div><div><br></div><div>template <typename T> struct thing { using=
thing =3D T; };</div><div>template <typename T> struct thing<T*&g=
t; { T* thing(int, int); };</div></div></blockquote><div><br></div><div>The=
struct template was of course meant to be called 'foobar'.</div><div> =
;</div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8e=
x;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><br></=
div><div>template <typename T></div><div>void fn(int i, int j) {</div=
><div> auto x =3D foobar<T*>::thing(i, j); // Valid code, but i=
llegal under the new rule, because thing was assumed to be a type.</div><di=
v>};</div></div></blockquote><div><br></div></div></blockquote></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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_4194_8773529.1378418538348--
.
Author: David Krauss <potswa@gmail.com>
Date: Thu, 5 Sep 2013 16:19:08 -0700 (PDT)
Raw View
------=_Part_5912_11400581.1378423148731
Content-Type: text/plain; charset=ISO-8859-1
I'm not slogging my way through all the walls of text, but judging by the
example it looks like someone suggested to use the primary template as the
source of declarations. That disagrees with what I read from the OP (which
I must admit is not the entirety of it). The last paragraph mentions
concepts as the basis for presumed declarations.
All we need is to allow concept-style declarations in namespace scope as
well as template parameter list scope.
So the Standard Library just has to say internally:
__IteratorTrait iterator_traits; // Maybe add a template keyword sprinkled
somewhere. Or maybe not.
and the requirements listed in the iterator traits table are applied to all
specializations.
Likewise foobar should conform to a concept that declares thing. I don't
see the advantage to getting all the members of a template; only the
interface is relevant and concepts are the right tool for template
interface specification.
It's probably better to avoid different interface specifications for
different specializations. Such a thing could be useful, but better syntax
might be to apply constraints to an alias template mapping to the relevant
specializations, which may or may not coincide with a partial
specialization implementation.
--
---
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_5912_11400581.1378423148731
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I'm not slogging my way through all the walls of text, but=
judging by the example it looks like someone suggested to use the primary =
template as the source of declarations. That disagrees with what I read fro=
m the OP (which I must admit is not the entirety of it). The last paragraph=
mentions concepts as the basis for presumed declarations.<br><br>All we ne=
ed is to allow concept-style declarations in namespace scope as well as tem=
plate parameter list scope.<br><br>So the Standard Library just has to say =
internally:<br><br><div class=3D"prettyprint" style=3D"background-color: rg=
b(250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; bo=
rder-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div c=
lass=3D"subprettyprint"><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify">__IteratorTrait iterator_traits</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-=
prettify">// Maybe add a template keyword sprinkled somewhere. Or maybe not=
..</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></spa=
n></div></code></div><br>and the requirements listed in the iterator traits=
table are applied to all specializations.<br><br>Likewise <span style=3D"f=
ont-family: courier new,monospace;">foobar</span> should conform to a conce=
pt that declares <span style=3D"font-family: courier new,monospace;">thing<=
/span>. I don't see the advantage to getting all the members of a template;=
only the interface is relevant and concepts are the right tool for templat=
e interface specification.<br><br>It's probably better to avoid different i=
nterface specifications for different specializations. Such a thing could b=
e useful, but better syntax might be to apply constraints to an alias templ=
ate mapping to the relevant specializations, which may or may not coincide =
with a partial specialization implementation.<br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_5912_11400581.1378423148731--
.
Author: David Krauss <potswa@gmail.com>
Date: Thu, 5 Sep 2013 16:19:19 -0700 (PDT)
Raw View
------=_Part_5647_10871403.1378423159593
Content-Type: text/plain; charset=ISO-8859-1
I'm not slogging my way through all the walls of text, but judging by the
example it looks like someone suggested to use the primary template as the
source of declarations. That disagrees with what I read from the OP (which
I must admit is not the entirety of it). The last paragraph mentions
concepts as the basis for presumed declarations.
All we need is to allow concept-style declarations in namespace scope as
well as template parameter list scope.
So the Standard Library just has to say internally:
__IteratorTrait iterator_traits; // Maybe add a template keyword sprinkled
somewhere. Or maybe not.
and the requirements listed in the iterator traits table are applied to all
specializations.
Likewise foobar should conform to a concept that declares thing. I don't
see the advantage to getting all the members of a template; only the
interface is relevant and concepts are the right tool for template
interface specification.
It's probably better to avoid different interface specifications for
different specializations. Such a thing could be useful, but better syntax
might be to apply constraints to an alias template mapping to the relevant
specializations, which may or may not coincide with a partial
specialization implementation.
--
---
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_5647_10871403.1378423159593
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I'm not slogging my way through all the walls of text, but=
judging by the example it looks like someone suggested to use the primary =
template as the source of declarations. That disagrees with what I read fro=
m the OP (which I must admit is not the entirety of it). The last paragraph=
mentions concepts as the basis for presumed declarations.<br><br>All we ne=
ed is to allow concept-style declarations in namespace scope as well as tem=
plate parameter list scope.<br><br>So the Standard Library just has to say =
internally:<br><br><div class=3D"prettyprint" style=3D"background-color: rg=
b(250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; bo=
rder-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div c=
lass=3D"subprettyprint"><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify">__IteratorTrait iterator_traits</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-=
prettify">// Maybe add a template keyword sprinkled somewhere. Or maybe not=
..</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></spa=
n></div></code></div><br>and the requirements listed in the iterator traits=
table are applied to all specializations.<br><br>Likewise <span style=3D"f=
ont-family: courier new,monospace;">foobar</span> should conform to a conce=
pt that declares <span style=3D"font-family: courier new,monospace;">thing<=
/span>. I don't see the advantage to getting all the members of a template;=
only the interface is relevant and concepts are the right tool for templat=
e interface specification.<br><br>It's probably better to avoid different i=
nterface specifications for different specializations. Such a thing could b=
e useful, but better syntax might be to apply constraints to an alias templ=
ate mapping to the relevant specializations, which may or may not coincide =
with a partial specialization implementation.<br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_5647_10871403.1378423159593--
.
Author: cornedbee@google.com
Date: Fri, 6 Sep 2013 05:19:33 -0700 (PDT)
Raw View
------=_Part_349_10835523.1378469973988
Content-Type: text/plain; charset=ISO-8859-1
On Friday, September 6, 2013 12:02:18 AM UTC+2, Bengt Gustafsson wrote:
> Well, my initial motivation for this suggestion was actually to simplify
> teaching, as it is quite hard for people to understand that even though the
> compiler has seen that add_const<T>::type is a type it chooses to ignore
> this fact...
>
Do you have any data on this? My experience has been that "but look, you
can specialize the template so that it means something completely
different" has always been enough to make people understand that the
compiler doesn't "ignore this fact", but genuinely can't know.
> In contrast it is very easy to understand that T::value_type can't be
> known to be a type. I don't think that a rule that has fewer words is
> always easier to learn, if it doesn't seem logical. In this case the new
> tutorial text would be "put a typename in if the compiler doesn't know if
> the dependant name is a type [from looking at the main template]".
>
That's easy to learn. It just delegates the actual decision to an
understanding of how the compiler works. A rule should say, "if the source
looks like this, do this", not "if some entity thinks you should do this,
do it". The latter isn't actually helpful.
> I don't think that the last part of the sentence is needed, even. It would
> only be interesting if someone came up with your code-breaking idea.
>
Without that last part, it becomes even more opaque.
>
> Your breaking code is indisputable of course, but I don't know if anybody
> has really a good use case for changing from type to function in a
> specialization. In your particular example it would be possible to know
> that the code is valid, but I admit that I was really hoping not to have to
> inspect specializations, this makes the implementation problem much worse.
>
No, it makes it impossible. If you can't make your idea work with the
primary template alone, it's not feasible. As you correctly said before,
the specializations might not even be available yet.
> But if the committee finds that it is ok to break all code that has a
> "using namespace std" and has a class called Object (which I hope they
> don't),
>
In the majority, they do. They broke everyone who has a class called array
or thread or mutex in C++11, and will do it again with every library
extension. And in particular, I don't think you'll find anyone on the
committee that will think "but it's CamelCase, I thought it was safe from
standard names" is a reasonable argument.
> I would say that "specialize a class template so that a name of a type is
> a function/member" is a worse breakage of coding discipline,
>
It's not. It's "I'm relying on the language to keep working as it does
now", not "I'm going to pull every present and future identifier in the
standard namespace into the global namespace".
> much less commonoly occurring
>
True.
> and easier to fix
>
Not true. Without knowing what use cases this would affect, how can you say
it would be easier to fix?
> and should thus be more acceptable.
>
It's a core language breaking change. That's never more acceptable than
adding to the standard library.
> On the other hand, as we can now write:
>
> template<typename T> using add_const = const T;
>
> and then add_const<T> without both the leading typename and the trailing
> ::type I think that the use for this suggestion is diminished from the code
> clutter standpoint.
>
Yes.
> Now, if we could only find a way to get rid of the _t on the names of the
> usings for new code, I would be quite happy...
>
Well, it's just a bunch of template aliases. You're welcome to write your
own header for them. I don't mind two extra characters.
--
---
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_349_10835523.1378469973988
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, September 6, 2013 12:02:18 AM UTC+2, Bengt Gust=
afsson wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr">Well, my initial motivation for this suggestion was actually to simplif=
y teaching, as it is quite hard for people to understand that even though t=
he compiler has seen that add_const<T>::type is a type it chooses to =
ignore this fact...</div></blockquote><div><br></div><div>Do you have any d=
ata on this? My experience has been that "but look, you can specialize the =
template so that it means something completely different" has always been e=
nough to make people understand that the compiler doesn't "ignore this fact=
", but genuinely can't know.</div><div> </div><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"> In contrast it is very easy to under=
stand that T::value_type can't be known to be a type. I don't think that a =
rule that has fewer words is always easier to learn, if it doesn't seem log=
ical. In this case the new tutorial text would be "put a typename in if the=
compiler doesn't know if the dependant name is a type [from looking at the=
main template]".</div></blockquote><div><br></div><div>That's easy to lear=
n. It just delegates the actual decision to an understanding of how the com=
piler works. A rule should say, "if the source looks like this, do this", n=
ot "if some entity thinks you should do this, do it". The latter isn't actu=
ally helpful.</div><div> </div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div dir=3D"ltr"> I don't think that the last part of the sentence is=
needed, even. It would only be interesting if someone came up with your co=
de-breaking idea.</div></blockquote><div><br></div><div>Without that last p=
art, it becomes even more opaque.</div><div> </div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr"><div><br></div><div><span styl=
e=3D"font-size:13px">Your breaking code is indisputable of course, but I do=
n't know if anybody has really a good use case for changing from type to fu=
nction in a specialization. </span><span style=3D"font-size:13px">&nbs=
p;</span><span style=3D"font-size:13px">In your particular example it would=
be possible to know that the code is valid, but I admit that I was really =
hoping not to have to inspect specializations, this makes the implementatio=
n problem much worse.</span></div></div></blockquote><div><br></div><div>No=
, it makes it impossible. If you can't make your idea work with the primary=
template alone, it's not feasible. As you correctly said before, the speci=
alizations might not even be available yet.</div><div> </div><blockquo=
te 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><span style=3D"fo=
nt-size:13px"> But if the committee finds that it is ok to break all c=
ode that has a "using namespace std" and has a class called Object (which I=
hope they don't),</span></div></div></blockquote><div><br></div><div>In th=
e majority, they do. They broke everyone who has a class called array or th=
read or mutex in C++11, and will do it again with every library extension. =
And in particular, I don't think you'll find anyone on the committee that w=
ill think "but it's CamelCase, I thought it was safe from standard names" i=
s a reasonable argument.</div><div> </div><blockquote class=3D"gmail_q=
uote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pad=
ding-left: 1ex;"><div dir=3D"ltr"><div><span style=3D"font-size:13px"> I wo=
uld say that "specialize a class template so that a name of a type is a fun=
ction/member" is a worse breakage of coding discipline,</span></div></div><=
/blockquote><div><br></div><div>It's not. It's "I'm relying on the language=
to keep working as it does now", not "I'm going to pull every present and =
future identifier in the standard namespace into the global namespace".</di=
v><div> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0;mar=
gin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D=
"ltr"><div><span style=3D"font-size:13px"> much less commonoly occurring</s=
pan></div></div></blockquote><div><br></div><div>True.</div><div> </di=
v><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><span =
style=3D"font-size:13px"> and easier to fix</span></div></div></blockquote>=
<div><br></div><div>Not true. Without knowing what use cases this would aff=
ect, how can you say it would be easier to fix?</div><div> </div><bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-l=
eft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><span style=
=3D"font-size:13px"> and should thus be more acceptable.</span></div></div>=
</blockquote><div><br></div><div>It's a core language breaking change. That=
's never more acceptable than adding to the standard library.</div><div>&nb=
sp;</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div=
>On the other hand, as we can now write:<br></div><div><span style=3D"font-=
size:13px"><br></span></div><div>template<typename T> using add_const=
=3D const T;</div><div><br></div><div>and then add_const<T> without =
both the leading typename and the trailing ::type I think that the use for =
this suggestion is diminished from the code clutter standpoint.</div></div>=
</blockquote><div><br></div><div>Yes.</div><div> </div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #=
ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div> Now, if we could only =
find a way to get rid of the _t on the names of the usings for new code, I =
would be quite happy...</div></div></blockquote><div><br></div><div>Well, i=
t's just a bunch of template aliases. You're welcome to write your own head=
er for them. I don't mind two extra characters.</div><div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_349_10835523.1378469973988--
.