Talk:Constrained genericity: Difference between revisions

→‎C++ example, concepts and C++0x: Code moved to discussion page because concepts were voted out of C++
(→‎C++ example, concepts and C++0x: Code moved to discussion page because concepts were voted out of C++)
Line 6:
: One possibility would be to park the code on the discussion page (or maybe I park it in a subpage of my user page) until (hopefully) concepts get reintroduced to a later version of the standard.
: When I added the entry, I was completely convinced that concepts would come (after all, they had been a highlighted feature of the next C++ version, and a lot of other features were defined in terms of concepts at that time). --[[User:Ce|Ce]] 20:22, 27 August 2010 (UTC)
 
==C++ code moved here==
Concepts have been removed from C++0x, but might appear in some future version. Code parked here to be put back if concepts reappear. --[[User:Ce|Ce]] 07:22, 9 September 2010 (UTC)
 
=== The moved section ===
The current C++ standard doesn't support constrained genericity (however you can emulate it by having the container refer to the corresponding eat function without actually calling it). The next version will, however, allow it through concepts:
<lang cpp>#include <concepts>
#include <vector>
 
auto concept Eatable<typename T> // auto makes it apply automatically
{
void eat(T);
};
 
template<std::Moveable T>
requires Eatable<T>
class FoodBox
{
public:
std::vector<T> food;
};</lang>
The only requirement to implement an Eatable type is, indeed, that a suitable function <tt>eat</tt> is defined for it (to put it in the FoodBox, in addition it has to be Moveable, since <tt>std::vector</tt> requires that; but that's ortogonal to the type being Eatable). A possible implementation of an eatable type could be:
<lang cpp>class Banana {};
void eat(Banana const &) {}</lang>
Even a built-in type can be made eatable by defining a suitable <tt>eat</tt> function. The following makes <tt>double</tt> an eatable type:
<lang cpp>void eat(double) {}</lang>
 
Another way to make an existing type eatable is to use a concept map. Let's assume we have an abstract base class <tt>Food</tt> which looks like this;
<lang cpp>class Food
{
public:
virtual void munch() = 0;
virtual ~Food() {}
};</lang>
Then we can make all classes derived from Food eatable using <tt>Food::munch()</tt> for <tt>eat</tt> with the following concept map template:
<lang cpp>template<std::DerivedFrom<Food> T>
concept_map Eatable<T>
{
void eat(T const& t) { t->munch(); }
}</lang>
The difference to a global function <tt>void eat(Food const&)</tt> is that the function in the concept map is only visible to functions using that concept, thus reducing namespace polution. Functions directly operating on <tt>Food</tt> objects can use the interface provided by <tt>Food</tt> itself, e.g. <tt>apple.munch()</tt>, or explicitly invoke <tt>Eatable<Food>::eat(apple)</tt>. Of course, concept maps also work with built-in types:
<lang cpp>concept_map Eatable<int>
{
void eat(int) {}
}</lang>
973

edits