Concepts didn't make the C++0x standard, but Boost still provides The Boost Concept Check Library (BCCL). I guess that BCCL doesn't cover everything that was meant to into the C++0x standard. What is the difference between BCCL and the proposed C++0x solution?
template<typename InputIterator>
int distance(InputIterator a, InputIterator b)
{ return b - a; }
You may now sprinkle that template with concept checks and traits, but you will never get an error after writing that template - because the Standard allows the compiler to delay compiling the template until instantiation. For checking, you have to write "archetype" classes, which contain exactly those operations that are required by the interface and then instantiate them artificially.
Reading the documentation of BCCL, i found it already includes the common archetypes like "default constructible". But if you write your own concepts, you will have to also provide your own archetypes, which isn't easy (you have to find exactly the minimal functionality a type has to provide). For example, if your archetype contains a operator-
, then the test of your template with that (incorrect) archetype will succeed, although the concepts don't require such an operator.
The rejected concepts proposal creates archetypes for you automatically, based on the requirements that were specified and that were implied (a pointer type T*
used in a parameter will imply the PointeeType requirement for T
, for example). You don't have to care about this stuff - except of course when your template definition contains a type error.
Consider this code, using hypothetical concept checks
template<ForwardIterator I>
void f(I a, I b) {
// loop two times!
loopOverAToB(a, b);
loopOverAToB(a, b);
}
The BCCL manual says that semantic requirements are not checked. Only syntax requirement and types are checked. Consider a forward iterator: There exists the semantic requirement that you may use it in multi-pass algorithms. Syntax-checking only won't be able to test this requirement (think about what happens if a stream iterator accidentally would pass that check!)
In the rejected proposal, you had to explicitly put auto
in front of concept definitions to make the compiler flag success after syntax-checking. If auto
wasn't specified, then a type explicitly had to define a concept map to say it supports that concept. A stream iterator would thus never be taken to pass a ForwardIterator check.
template<InputIterator I>
requires OutputStreamable<I::value_type>
void f(I a, I b) {
while(a != b) std::cout << *a++ << " ";
}
Can be used like the following, if the user would provide a concept map that teaches the compiler how to dereference an integer, and thus how an integer satisfies the InputIterator concept.
f(1, 10);
This is the benefit of a language-based solution, and cannot be solved by BCCL ever, i believe.
template<ForwardIterator I>
I::difference_type distance(I a, I b) {
I::difference_type d = 0; while(a != b) ++a, ++d;
return d;
}
template<RandomAccessIterator I>
I::difference_type distance(I a, I b) {
return b - a;
}
If a type could be used with both templates, then the second template would be used, because it's more specialized: RandomAccessIterator
refines the ForwardIterator
concept.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With