Topic: C++0x: hole in concept system
Author: SG <s.gesemann@gmail.com>
Date: Fri, 20 Feb 2009 12:29:29 CST Raw View
On 4 Feb., 16:39, Douglas Gregor <doug.gre...@gmail.com> wrote:
> You are correct. This fails at instantiation time, and is one of the
> holes in the concepts type system.
>
> This hole was intentionally put into concepts by the committee to
> address concerns about the performance of generated code. In
> particular, the committee wanted to be sure that, from a simple
> concept specification like
>
> concept HasFoo<typename T> {
> void foo(const T&);
> }
>
> a constrained template, when instantiated, would still be able to
> chose among different overloads to get the fastest version, e.g.,
Of course. It just didn't occur to me that this represents a trade-off
and that we can't have both. I'm still wondering, though.
But I'm sure you and other committee members have put a lot of thought
into it before you got to this conclusion. Thanks for this
clarification!
> Bellevue meeting in Spring 2008, where concepts gained this hole. For
> more information about the various issues and possible solutions,
> please see
>
> http://www.open-std.org/JTC1/sc22/wg21/docs/papers/2008/n2576.pdf
>
> The committee opted for the solution in 4.2.
This pointer is very much appreciated. For someone who hasn't read it
this "concepts hole" may seem like an oversight.
Cheers!
SG
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: SG <s.gesemann@gmail.com>
Date: Sat, 31 Jan 2009 14:40:38 CST Raw View
Hi!
This is not (yet) a "formal issue" as far as the committee is
concerned but I think it should be.
The problem is with function requirements in the current draft. They
are introduced early on in chapter 14 but their exact meaning with
respect to rvalue/lvalue parameter binding is left unclear. Later, we
can read about how the compiler is supposed to check whether a
concept_map is well formed (14.9.2.1 for function requirements).
Ideally these kinds of checking rules somehow match those for type
checking constrained templates. Otherwise, we would have type errors
that are delayed until instantiation which defeats the purpose of
having concepts. Unfortunately I was not able to find informations on
how function requirements are treated in constrained contexts.
Here's an example of the problem:
concept HasFoo<typename T>
{
void foo(T); // What is this supposed to mean?
}
template<typename T>
requires HasFoo<T>
void bar(const T& x)
{
foo(x); // OK! ConceptGCC accepts this. I didn't find any
specific
// rules in the current draft that say how function requirements
are
// translated to "arche functions" except for some special non-
static
// member functions (see chapter about assembling arche types).
}
void foo(const int&) = delete; // Not yet supported by ConceptGCC.
void foo(int &&) {} // foo only accepts non-const
rvalues
concept_map HasFoo<int> {} // OK! According to the rules in
14.9.2.1
// that only require an expression of the form foo(p) (where p is an
// rvalue of type int) to be well-formed.
int main()
{
bar<int>(42); // Fail! It can't possibly work. We've got a hole
// in the concept system.
}
So, the problem I addressed in an earlier thread about member function
ref qualifiers extends to normal function parameters as well.
I have no solution but IMHO this needs fixing. Can somebody verify?
Cheers!
SG
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Douglas Gregor <doug.gregor@gmail.com>
Date: Wed, 4 Feb 2009 09:39:18 CST Raw View
On Jan 31, 12:40 pm, SG <s.gesem...@gmail.com> wrote:
> Hi!
>
> This is not (yet) a "formal issue" as far as the committee is
> concerned but I think it should be.
>
> The problem is with function requirements in the current draft. They
> are introduced early on in chapter 14 but their exact meaning with
> respect to rvalue/lvalue parameter binding is left unclear. Later, we
> can read about how the compiler is supposed to check whether a
> concept_map is well formed (14.9.2.1 for function requirements).
> Ideally these kinds of checking rules somehow match those for type
> checking constrained templates. Otherwise, we would have type errors
> that are delayed until instantiation which defeats the purpose of
> having concepts.
> Unfortunately I was not able to find informations on
> how function requirements are treated in constrained contexts.
They're just functions, and they act is if you had just declared them
within the scope of your template.
> Here's an example of the problem:
>
> concept HasFoo<typename T>
> {
> void foo(T); // What is this supposed to mean?
> }
>
> template<typename T>
> requires HasFoo<T>
> void bar(const T& x)
> {
> foo(x); // OK! ConceptGCC accepts this. I didn't find any
> specific
> // rules in the current draft that say how function requirements
> are
> // translated to "arche functions" except for some special non-
> static
> // member functions (see chapter about assembling arche types).
> }
The call to "foo" should have been rejected, because 'T' does not have
a copy constructor. ConceptGCC doesn't do this because it actually
implies the CopyConstructible<T> requirement from the function
requirement
void foo(T)
That implication is no longer in the specification, because
CopyConstructible<T> is too strict a requirement here. (One could have
a move-constructor, for example).
This, on the other hand, is well-formed:
template<typename T>
requires HasFoo<T> && CopyConstructible<T>
void saloon(const T& x) {
foo(x); // okay, calls T's copy constructor to create a temporary
for foo(x)
};
> void foo(const int&) = delete; // Not yet supported by ConceptGCC.
> void foo(int &&) {} // foo only accepts non-const
> rvalues
>
> concept_map HasFoo<int> {} // OK! According to the rules in
> 14.9.2.1
> // that only require an expression of the form foo(p) (where p is an
> // rvalue of type int) to be well-formed.
Correct.
> int main()
> {
> bar<int>(42); // Fail! It can't possibly work. We've got a hole
> // in the concept system.
> }
>
You are correct. This fails at instantiation time, and is one of the
holes in the concepts type system.
This hole was intentionally put into concepts by the committee to
address concerns about the performance of generated code. In
particular, the committee wanted to be sure that, from a simple
concept specification like
concept HasFoo<typename T> {
void foo(const T&);
}
a constrained template, when instantiated, would still be able to
chose among different overloads to get the fastest version, e.g.,
template<HasFoo T> requires std::DefaultConstructible<T>
void pub() {
foo(T()); // okay: rvalue binds to the reference-to-const
}
then, we'll do the same thing you did above, with a slight twist:
class Matrix { /* big and heavy */ };
void foo(const Matrix& x); // makes a copy of x internally. slow!
void foo(Matrix&& x); // reuses the x that it gets. faster!
concept_map HasFoo<Matrix> { };
then, call pub<Matrix>, which will then perform overload resolution
and will end up calling
void foo(Matrix&& x)
with the default-constructed Matrix temporary. So, instantiation-time
overloading has benefits for performance but opens up a type hole in
the system. This was discussed at length in the committee at it's
Bellevue meeting in Spring 2008, where concepts gained this hole. For
more information about the various issues and possible solutions,
please see
http://www.open-std.org/JTC1/sc22/wg21/docs/papers/2008/n2576.pdf
The committee opted for the solution in 4.2.
- Doug
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]