Re: With Concepts, it seems a truly heterogeneous container is almost there, but...
Vidar Hasfjord wrote:
Lourens Veen wrote:
But that would mean a major change to C++. You would have to have
type names and function signatures available at runtime, and have
some sort of runtime call-by-name mechanism. Also all objects would
have to carry type information with them (which may include
information on a large inheritance hierarchy, so that an inherited
member function can be called). In essence, you would have to
introduce dynamic typing to C++. It's probably possible, yes, but
I'm not sure whether it would still be C++.
Unless I've overlooked something, I think you are overstating things
a bit here. Although RTTI is needed to select the function to call,
the type information derived from the concept determines function
signatures at compile time.
Ah, yes, that's possible. I'd overlooked that. So you don't need to do
overload resolution at runtime.
AFAIKT a mechanism similar to virtual
functions can be used. Using OP's example, the call {textable.text
("...");} could generate the following pseudo code:
const __Textable::vtable* vtbl =
__Textable::lookup_vtable (typeid (textable));
assert (vtbl);
(*vtbl) [__Textable::text_index] (&textable, "...");
So then the concept should have a vtable for each type matching the
concept? How does that work with different translation units? The
linker could merge them I suppose.
On the other hand, if it walks like a duck, talks like a duck, and
should be seen as a duck by everyone stocking it, then the code
should reflect that. The proper way to express this relationship is
to derive "it" from a "duck" abstract class.
Well, that's not a solution if you have no access to the code in
question. The obvious example being libraries. Duck-typing is most
useful for types over which you have no control.
The thought had crossed my mind, yes. Actually, IIRC AspectJ allows
you to change an existing inheritance hierarchy, injecting such a
common base class, for the same reason.
The OP's example
doesn't highlight this. Here's another example (using invented
syntax
{auto <Concept>} to name a "heterogenous type"):
// --- Their code ---
namespace Vendor1 {
class HtmlElement {
public:
std::string GetContent () const;
};
}
namespace Vendor2 {
struct html_element {...};
const char* get_content (const html_element*);
}
// --- Our alternative code ---
namespace ours {
struct HtmlElement {
virtual std::string getContent() const = 0;
};
class HtmlElement1 : public HtmlElement {
::Vendor1::HtmlElement el;
public:
std::string getContent() const {
return el.GetContent();
}
};
struct HtmlElement2 : public HtmlElement {
::Vendor2::html_element el;
public:
std::string getContent() const {
return std::string(::Vendor2::get_content(el));
}
};
class ContentCollection {
std::vector<HtmlElement> container;
};
}
If I understand you correctly, this is essentially how you propose to
implement the concept version (i.e. it could compile down to the same
code)?
I'm a little mixed about this style-wise. On the one hand the concept
version is more abstract and perhaps cleaner, on the other hand I
wonder if we're not sweeping too much of the type system and what's
actually happening under the carpet. Maybe I just have to get used to
the idea.
Lourens
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]