Topic: Concepts and incomplete classes
Author: David Krauss <potswa@gmail.com>
Date: Fri, 30 Aug 2013 03:50:05 -0700 (PDT)
Raw View
------=_Part_537_15147426.1377859805002
Content-Type: text/plain; charset=windows-1252
Content-Transfer-Encoding: quoted-printable
Concepts potentially improve any template by checking requirements on=20
incoming arguments. But some templates, including all CRTP bases, accept=20
incomplete classes as arguments. Moreover, deferring dependencies is a=20
positive trait of any template. For example, any container accepting an=20
incomplete element type can implement a multi-tree, if passed its own=20
incomplete type. As long as the effect of a concept requirement is to=20
render the program ill-formed upon failure, so it doesn't matter *when*fail=
ure occurs.
Partially specializing a CRTP base on the interface implemented by its=20
derived class obviously presents a conundrum. But for example, partially=20
specializing a container on its allocator argument, and also constraining=
=20
its element type argument, which may be incomplete, should be allowed.=20
Deferred constraints are useless for making decisions and it seems they=20
should simply be ignored, or treated as satisfied at the actual point of=20
instantiation. Then overload resolution can proceed with the remaining,=20
non-deferred constraints.
The need seems to really exist, but I'm not sure how the interface should=
=20
work. The potentially-incomplete class should be tagged as such, and the=20
constraint checking should be deferred until all such-marked classes are=20
complete.
No interface is strictly necessary. A compliant implementation could=20
already defer all constraint checking until all class types are complete=20
(or the TU ends), since a constraint is an odr-use of a class and if two=20
points of instantiation see different definitions of a class type=20
(incomplete and complete), the program is ill-formed with no diagnostic=20
required. But tolerance of incomplete classes is the exception rather than=
=20
the rule, so explicitness is probably better.
The best thing that comes to mind is to have an alias template std::complet=
e_type_of<=20
T > which resolves to T, but has the side effect of halting any=20
instantiation of a concept template, and deferring the result to another=
=20
point of instantiation, such as at the end of the TU, or after the=20
definition of the given type. (Every template is ideally instantiated again=
=20
at the end of every TU, for the purpose of determining well-formedness, but=
=20
no diagnostic is required.)
It's possible to model this sort of thing by putting class-wide constraints=
=20
somewhere else, for example on a dummy function instantiated when the=20
parameter is odr-used. But that's hackish. And, I want to make a formal=20
proposal to infer member names from requirements, for the purpose of=20
reducing excessive template and typename keywords, and such workarounds=20
would defeat that.
I just worked through this approach while writing up this message=85 surely=
=20
there must be other ways. I hope someone else comes up with another=20
alternative, or that there is some interest in this!
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_537_15147426.1377859805002
Content-Type: text/html; charset=windows-1252
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Concepts potentially improve any template by checking requ=
irements on incoming arguments. But some templates, including all CRTP base=
s, accept incomplete classes as arguments. Moreover, deferring dependencies=
is a positive trait of any template. For example, any container accepting =
an incomplete element type can implement a multi-tree, if passed its own in=
complete type. As long as the effect of a concept requirement is to render =
the program ill-formed upon failure, so it doesn't matter <i>when</i> failu=
re occurs.<br><br>Partially specializing a CRTP base on the interface imple=
mented by=20
its derived class obviously presents a conundrum. But for example,=20
partially specializing a container on its allocator argument, and also=20
constraining its element type argument, which may be incomplete, should=20
be allowed. Deferred constraints are useless for making decisions and it
seems they should simply be ignored, or treated as satisfied at the=20
actual point of instantiation. Then overload resolution can proceed with
the remaining, non-deferred constraints.<br><br>The need seems to really e=
xist, but I'm not sure how the interface should work. The potentially-incom=
plete class should be tagged as such, and the constraint checking should be=
deferred until all such-marked classes are complete.<br><br>No interface i=
s strictly necessary. A compliant implementation could already defer all co=
nstraint checking until all class types are complete (or the TU ends), sinc=
e a constraint is an odr-use of a class and if two points of instantiation =
see different definitions of a class type (incomplete and complete), the pr=
ogram is ill-formed with no diagnostic required. But tolerance of incomplet=
e classes is the exception rather than the rule, so explicitness is probabl=
y better.<br><br>The best thing that comes to mind is to have an alias temp=
late <span style=3D"font-family: courier new,monospace;">std::complete_type=
_of< T ></span> which resolves to T, but has the side effect of halti=
ng any instantiation of a concept template, and deferring the result =
to another point of instantiation, such as at the end of the TU, or after t=
he definition of the given type. (Every template is ideally instantiated ag=
ain at the end of every TU, for the purpose of determining well-formedness,=
but no diagnostic is required.)<br><br>It's possible to model this sort of=
thing by putting class-wide constraints somewhere else, for example on a d=
ummy function instantiated when the parameter is odr-used. But that's hacki=
sh. And, I want to make a formal proposal to infer member names from requir=
ements, for the purpose of reducing excessive <span style=3D"font-family: c=
ourier new,monospace;">template</span> and <span style=3D"font-family: cour=
ier new,monospace;">typename</span> keywords, and such workarounds would de=
feat that.<br><br>I just worked through this approach while writing up this=
message=85 surely there must be other ways. I hope someone else comes up w=
ith another alternative, or that there is some interest in this!<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_537_15147426.1377859805002--
.