Grr. That's no so easy either, because it conflicts with the one-argument
specialized constructor.
Either I have to write separate constructors for std::vector<ValType> and
SmallVector<ValType, Size> or I take an alternate approach.
I've opted for the alternate approach: make all clients pass iterators. That
is, get rid of the specialized one- and two-argument constructors entirely.
This gets rid of all of these headaches while at the same time reducing code
size and maintenance costs. It does require that clients store their
arguments in an array of some sort, but it's probably not a bad tradeoff.
It at least makes everything consistent.
What do you think?
-Dave
Actually, I just got rid of the two-argument version, because that's the
one that interference with the iterator template version.
-Dave
That sounds reasonable. Please keep the "Value* + num elements" ctor as well though.
Here's another crazy idea. Instead of overloading the callinst ctor, why not just add a static function to create the call (like binaryoperator and friends):
C = CallInst::CreateWithArgRange(X, B, V.begin(), V.end());
That way you can completely avoid the overloading issues.
-Chris
> I've opted for the alternate approach: make all clients pass iterators.
> That is, get rid of the specialized one- and two-argument constructors
> entirely.
That sounds reasonable. Please keep the "Value* + num elements" ctor as
well though.
Why? I can't think of a case where a client uses that but can't use the
iterator version (just pass Value, Value+num). I'd rather not maintain two
interfaces with identical semantics.
Here's another crazy idea. Instead of overloading the callinst ctor, why
not just add a static function to create the call (like binaryoperator and
friends):
C = CallInst::CreateWithArgRange(X, B, V.begin(), V.end());
That way you can completely avoid the overloading issues.
That's not a bad idea. In fact, we ought to think about creating factories
for everything. Bare new/delete usually comes back to haunt one later on.
I'll get what I've got working and checked in. I'm not sure I'm ready to go
and change everything to CallInst factories given the tons of other things
I've got to work on.
The iterator and one-argument constructors appear to cover 99% of the
cases and the two-argument clients can often just pass Use::op_iterators
directly. I've even found one case where we can eliminate a temporary vector.
-Dave
What's the relationship of this idea to LLVMBuilder?
-Dave
I've opted for the alternate approach: make all clients pass iterators.
That is, get rid of the specialized one- and two-argument constructors
entirely.
That sounds reasonable. Please keep the "Value* + num elements" ctor as
well though.
Why? I can't think of a case where a client uses that but can't use the
iterator version (just pass Value, Value+num). I'd rather not maintain two
interfaces with identical semantics.
If nothing else, for temporary migration reasons. First step is to get the new interface in, second step is to migrate clients, third step is to remove the old one.
Here's another crazy idea. Instead of overloading the callinst ctor, why
not just add a static function to create the call (like binaryoperator and
friends):
C = CallInst::CreateWithArgRange(X, B, V.begin(), V.end());
That way you can completely avoid the overloading issues.
That's not a bad idea. In fact, we ought to think about creating factories
for everything. Bare new/delete usually comes back to haunt one later on.
Yep, I agree.
I'll get what I've got working and checked in. I'm not sure I'm ready to go
and change everything to CallInst factories given the tons of other things
I've got to work on.
Of course 
The iterator and one-argument constructors appear to cover 99% of the
cases and the two-argument clients can often just pass Use::op_iterators
directly. I've even found one case where we can eliminate a temporary vector.
nice!
-Chris
> Why? I can't think of a case where a client uses that but can't use the
> iterator version (just pass Value, Value+num). I'd rather not maintain
> two interfaces with identical semantics.
If nothing else, for temporary migration reasons. First step is to get
the new interface in, second step is to migrate clients, third step is to
remove the old one.
Actually, I've made all of the changes to the clients already. There weren't
a whole lot,. really.
> The iterator and one-argument constructors appear to cover 99% of the
> cases and the two-argument clients can often just pass Use::op_iterators
> directly. I've even found one case where we can eliminate a temporary
> vector.
nice!
Unfortunately, I spoke too soon. op_iterators are not compatible with this
code because the existing interfaces require a Value ** pointing to
contiguous memory. You can't get that directly with op_iterators because
of the additional Use information there. Too bad.
-Dave