- edited description
Misleading Vector copy constructor
There is an wrapping issue when creating a copy of a Vector, i.e.
std::shared_ptr<GenericVector> a(new Vector(MPI_COMM_WORLD, 5));
std::shared_ptr<GenericVector> b(new Vector(*a));
a is an instance of Vector which wraps usually an PETScVector (accessible by a->instance()) b is an instance of Vector which wraps an Vector which wraps an PETScVector.
Performing now operations like
(*a) += (*b);
will cause an error within the "as_type" method. The += operator is called on Vector which calls the += on PETScVector with an GenericVector as argument. This tries to cast the right hand side (*b) to an PETScVector via "as_type", returning a
dynamic_cast<PETScVector&>(*b->instance());
However this fails since b->instance() is of type Vector.
The complete issue is caused by the GenericVector constructor of Vector
Vector(const GenericVector& x) : vector(x.copy()) {}
which wraps any GenericVector, also if it is an Vector.
It would be more logical to have an constructor like this:
Vector::Vector(const GenericVector& x) {
const Vector* vec = dynamic_cast<Vector*>(&x);
if (vec != NULL) {
vector.reset(vec->vector->copy());
}
else {
vector.reset(x.copy());
}
}
which would also be consistent with the copy constructor of Vector
Vector(const Vector& x) : vector(x.vector->copy()) {}
Here some additional code for testing:
#include <dolfin/la/dolfin_la.h>
#include <cxxabi.h>
#define TYPEOF(a) std::cout << "Type of " << #a << " is " << demangled_type_info_name(typeid(a)) << std::endl
// see http://stackoverflow.com/a/19005835
static inline std::string demangled_type_info_name(const std::type_info&ti)
{
int status = 0;
return abi::__cxa_demangle(ti.name(),0,0,&status);
}
using namespace dolfin;
main() {
std::shared_ptr<GenericVector> a (new Vector(MPI_COMM_WORLD, 5));
TYPEOF(*a);
TYPEOF(*a->instance());
std::cout << std::endl;
std::shared_ptr<GenericVector> b(new Vector(*a));
TYPEOF(*b);
TYPEOF(*b->instance());
TYPEOF(*dynamic_cast<Vector*>(b->instance())->instance());
std::cout << std::endl;
std::shared_ptr<GenericVector> c(a->copy());
TYPEOF(*c);
TYPEOF(*c->instance());
}
Comments (4)
-
reporter -
- changed milestone to 1.6
-
- changed milestone to 1.7
-
- removed milestone
Removing milestone: 1.7 (automated comment)
- Log in to comment