On Tue, 2009-09-01 at 10:19 +0200, David Engster wrote:
> Eric M. Ludlam <eric@...> writes:
> > On Tue, 2009-09-01 at 00:29 +0200, David Engster wrote:
> >> template <typename T> class test
> >> {
> >> public:
> >> void func1() { };
> >> };
> >>
> >> template <> class test <float>
> >> {
> >> public:
> >> void func2() { };
> >> };
> >>
> >> semanticdb-typecache-merge-streams doesn't know how to merge these
> >> types, so the first one is kept and the second one is silently dropped.
>
> [...]
>
> > In this case, a function that accepts two tags and chooses which one to
> > keep. This function doesn't need to handle the class/namespace merges,
> > nor the prototype vs impl selection which is already in the merge code.
> >
> > The default can return the first tag.
> >
> > This way, C can add some fancy stuff. Anything discovered in C that
> > works for other languages can be promoted back to the core typecache
> > code.
> >
> > As for what to actually DO with these two identical tags, I don't know.
> > I guess that depends on what the use cases are. The typecache is tuned
> > to return only one tag during a find by name. What might that tag be
> > that represents both of these things?
>
> Actually, I think we should not merge them at all, since they are two
> different types; you can do whatever you want in those type
> specializations. I'm more leaning towards renaming one of the tags,
> e.g., leaving 'test' for the generic one and 'test<float>' for the
> specialization. The dereferencer would then have to choose the correct
> one. Maybe this should already be done in the parsing stage.
>
> But maybe that won't play well with the existing template code; I don't
> know. I have to take a good look at it first.
>
> And there's another problem looming: partial template specialization. It
> works something like this:
>
> template <typename T> class test
> {
> public:
> void doSomething(T t) { };
> };
>
> template <typename T> class test<T *>
> {
> public:
> void doSomething(T* t) { };
> }
>
> That means, you can create a class that specially deals with pointers of
> type T (yes, also different ones for multiple levels of pointers).
>
> Oh, and you can (partially) specialize nested templates and templates
> with multiple type parameters. (How does one even name that? Multiple
> Template Parameter Partial Template Specialization?)
I would guess the first tactic is to make sure the C++ parser produces
tags that are distinct for these different permutations of "test". ie,
can you tell them apart based on the :template slot. Right now the
second doesn't parse at all for me. ;)
Then, in the typecache, when it finds two tags that differ only by
template specifier, argument lists, or other, it could fabricate a new
tag of class 'polymorphic, or a more descriptive
'bunch-o-tags-with-the-same-name. This tag would then have a :members
list. Since lots of programming languages use polymorphism, this could
be a generic tag class with a range of language overloadable features.
The hard part here is that every piece of code that deals with a return
value from the typecache would need to know about this new tag type, and
what to do about it. Code that performs a generic search would want to
know how to merge the results into one of these generic tags too. I
know the analyzer has a 'choose the best tag' function somewhere.
One way to simplify this problem is to have this new tag type scan the
list of members, find the most generic one, and promote it's features up
to the 'polymorphic tag itself. In that way, if the tag were misused by
something like eldoc, it would still print out as the basic tag.
Alternately, I suppose the merging of tags could clone the most generic
tag, and add a :polymorphic or :bunch-o-tags-with-the-same-name
attribute with the original list as a value. This might work better in
the above scenario. In fact, this would be almost exactly like what it
does now, except that code that cares would be able to look inside, and
make smarter decisions. I like that.
If I can dig up a few minutes I can prototype this concept, unless you
get to it first. I'd suggest a whole new support file for a
polymorphism handling API. It would be the place to go for solving
problems like this, of which there is no support now.
It could then take over semantic-analyze-select-best-tag prototype
filtering, and a few other things scattered randomly in the code.
> > Every time I try to simplify some problem, C++ finds an exception.
>
> Yep. Sometimes I think we should just take the risk and let C++ become
> self-aware, so that it can parse itself.
Hmmm. Isn't that what bison does? Perhaps it has happened already. ;)
Thanks for explaining this issue to me. I don't code much in C++
anymore.
Eric
|