want to pass vector<foo*> to fn expecting vector<const foo*>
Consider the following toy program:
[Disclaimer: This is an abstraction of a design problem I currently face
in "real" code. This is not a homework assignment.]
--- begin sample code ---
// investigate passing vector<foo*> to a function expecting vector<const foo*>
#include <cassert>
#include <vector>
#include <iostream>
using std::cout;
class interval
{
public:
int min() const { return min_; }
int max() const { return max_; }
void make_empty() { min_ = 0; max_ = -1; }
interval(int min_in, int max_in)
: min_(min_in), max_(max_in)
{ /* empty constructor body */ }
// default compiler-generated destructor is ok
// default compiler-generated copy ctor & assignment op are ok
private:
int min_, max_;
};
// prototype
void print_vector_of_intervals(const std::vector</* const */ interval*>& vci);
int main()
{
std::vector<interval*> vi;
vi.push_back(new interval(2,3));
vi.push_back(new interval(5,7));
vi.push_back(new interval(11,13));
print_vector_of_intervals(vi);
}
// print each interval pointed-to by a member of vci
// n.b. this function promises not to change the vector-of-pointers
// AND not to change the pointed-to intervals
void print_vector_of_intervals(const std::vector</* const */ interval*>& vci)
{
for (int i = 0 ; i < static_cast<int>(vci.size()) ; ++i)
{
const interval* pI = vci.at(i);
assert(pI != NULL);
const interval& I = *pI;
cout << "interval " << i << " = "
<< "[" << I.min() << ", " << I.max() << "]" << "\n";
}
}
--- end sample code ---
As written, the program is accepted without complaint by g++ 4.6.2 and
clang++ 3.0 (both with -W -Wall), and produces the expected output when
run.
However, as written there's a design weakness in the program:
print_vector_of_intervals() promises in its header comment not to change
the pointed-to intervals, but its prototype doesn't reflect that promise.
So, the "obvious" solution is to uncomment the commented-out "const" in
print_vector_of_intervals()'s prototype and its declaration, so that the
prototype looks like this:
void print_vector_of_intervals(const std::vector<const interval*>& vci);
Now the prototype makes explicit the semantics which were previous only
described in the comments, namely that print_vector_of_intervals() won't
modify the pointed-to intervals. (More precisely, that it won't call any
non-const interval:: member functions (such as interval::make_empty())
on the pointed-to intervals.)
Alas, now main isn't allowed to pass a std::vector<interval*> to
print_vector_of_intervals(): Both g++ and clang++ agree that the modified
code is invalid, because there's no known conversion from
std::vector<interval*>
to
std::vector<const interval*>
My basic question is, what to do about this? That is, what design(s)
can/should be used (in any/all of C++98, 03, or 11) so that client code
which has a std::vector<interval*> can pass (a reference to) that vector
to a function which promises not to change either the vector-of-pointers
or the pointed-to objects?
I can think of two obvious solutions... each with fairly obvious drawbacks:
(a) omit the "const" in the prototype & declaration of
print_vector_of_intervals()
(b) have client code copy the pointers to a temporary
vector-of-pointers-to-const-intervals, and then call
print_vector_of_intervals() on that temporary
Is there an elegant solution that I've overlooked?
[Of course for this toy program, it's easy to just have a vector of
intervals rather than a vector of pointers-to-intervals, but in my
"real" code the objects in question are large and noncopyable, so
vector-of-pointers is the appropriate data structure.]
thanks,
--
-- "Jonathan Thornburg [remove -animal to reply]" <jthorn@astro.indiana-zebra.edu>
Dept of Astronomy & IUCSS, Indiana University, Bloomington, Indiana, USA
on sabbatical in Canada starting August 2012
"Washing one's hands of the conflict between the powerful and the
powerless means to side with the powerful, not to be neutral."
-- quote by Freire / poster by Oxfam
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]