Created attachment 544 [details] program The attached program assert even though I only use Eigen::Vector3d: Assertion failed: (((SizeAtCompileTime == Dynamic && (MaxSizeAtCompileTime==Dynamic || size<=MaxSizeAtCompileTime)) || SizeAtCompileTime == size) && size>=0), function resize, file /Users/iljah/libraries/eigen/Eigen/src/Core/PlainObjectBase.h, line 282. Program received signal SIGABRT, Aborted. 0x00007fff8f531866 in __pthread_kill () (gdb) up #1 0x00007fff8c30635c in pthread_kill () (gdb) #2 0x00007fff8a6adb1a in abort () (gdb) #3 0x00007fff8a6779bf in __assert_rtn () (gdb) #4 0x0000000100000c87 in Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >::resize (this=0x7fff5fbffa98, size=0) at PlainObjectBase.h:282 282 eigen_assert(((SizeAtCompileTime == Dynamic && (MaxSizeAtCompileTime==Dynamic || size<=MaxSizeAtCompileTime)) || SizeAtCompileTime == size) && size>=0); (gdb) #5 0x0000000100000c05 in Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >::_init1<int> (this=0x7fff5fbffa98, size=0) at PlainObjectBase.h:713 713 resize(size); (gdb) #6 0x0000000100000b9a in Eigen::Matrix<double, 3, 1, 0, 3, 1>::Matrix<int> (this=0x7fff5fbffa98, x=@0x7fff5fbffa74) at Matrix.h:244 244 Base::template _init1<T>(x); (gdb) #7 0x0000000100000b3d in Eigen::Matrix<double, 3, 1, 0, 3, 1>::Matrix<int> (this=0x7fff5fbffa98, x=@0x7fff5fbffa74) at Matrix.h:245 245 } (gdb) #8 0x0000000100000b16 in f<Eigen::Matrix<double, 3, 1, 0, 3, 1> > (data=@0x7fff5fbffac8) at test.cpp:7 7 return T{0}; (gdb) #9 0x0000000100000a9c in main () at test.cpp:14 14 const Eigen::Vector3d v = f(data); Looks like the assert goes away if I use return T{0, 0, 0}; instead of return T{0}; This looks like a bug in initialization logic of Vector3d since that's what T is deduced to. I can't use {0, 0, 0} if T is double so supporting also scalar init of matrices would be nice. And looks like old style initialization with T(0) gives the same result.
You are calling Vector3d(0), which asserts as intended. What behavior would you expect? If you want a vector of zeros, you must use T::Constant(0) or T::Zero(). Adding a single parameter constructor which initializes fixed-sized matrices by that scalar is likely to cause more trouble than it solves.
> You are calling Vector3d(0), which asserts as intended. What behavior would > you expect? I'd expect http://en.cppreference.com/w/cpp/language/aggregate_initialization to work, specifically "If the number of initializer clauses is less than the number of members or initializer clauses is completely empty, the remaining members are initialized by"... > If you want a vector of zeros, you must use T::Constant(0) or T::Zero(). Which only works with Eigen as far as I know so I can't write a generic function that needs to initialize a template parameter to 0 without additional code for e.g. Eigen. > Adding a single parameter constructor which initializes fixed-sized matrices > by that scalar is likely to cause more trouble than it solves. Doesn't seem to be the case for standard types and as you can see some people will be surprised by Eigen not working similarly even though it could.
(In reply to Ilja Honkonen from comment #2) > > You are calling Vector3d(0), which asserts as intended. What behavior would > > you expect? > > I'd expect > http://en.cppreference.com/w/cpp/language/aggregate_initialization to work, > specifically "If the number of initializer clauses is less than the number > of members or initializer clauses is completely empty, the remaining members > are initialized by"... We don't have brace-or-equal initializers in Eigen. Could you just answer what values you expect Vector3d to have, if you initialize it, e.g., using Vector3d{1,2}; Vector3d{2}; Shall the remaining elements be 0.0, undefined or equal to the first element? std::array<double, 3> appears to initialize by 0 and I would not say that Vector3d{2}=={2,0,0} would be very intuitive.
I edited this bug to a feature request for C++11 initializer lists. I thought we had a request for that already, but maybe we just had a mailing list discussion. I'm still not convinced about supporting Vector3d{1}, or Vector3d{1,2}. Especially, the behavior of std::array I don't find intuitive at all.
> We don't have brace-or-equal initializers in Eigen. Could you just answer > what values you expect Vector3d to have, if you initialize it, e.g., using > Vector3d{1,2}; Vector3d{2}; > Shall the remaining elements be 0.0, undefined or equal to the first element? I would go with standard behavior, so unspecified items would be value-initialized which for doubles means zero-initialization if I'm reading cppref correctly and init of std::array also works. With this behavior I could use e.g. = T{0} + 2 to initialize both a double and a vector3d to 2 (, 2, 2, ...) assuming if eigen allowed + in addition to *... > std::array<double, 3> appears to initialize by 0 and I would not say that > Vector3d{2}=={2,0,0} would be very intuitive. What about Vector3d{}? Not initializing is an option but (http://en.cppreference.com/w/cpp/language/default_initialization) "If T is an array type, every element of the array is default-initialized." and to me eigen feels like an array type. VectorNd{1} looks like an exception because for e.g. Vector4d{1,2} none of the other options [(1,2,2,2), (1,2,1,2), (1,2,1,1) or even (1,2,2,1)] are any easier to remember. Standard behavior seems to be the only consistent way to initialize a vector when given no values {}, all values {a, b, c, ...} and everything in between. For dynamic matrices I suggest emulating behavior of http://en.cppreference.com/w/cpp/numeric/valarray/valarray
(In reply to Ilja Honkonen from comment #5) > I would go with standard behavior, so unspecified items would be > value-initialized which for doubles means zero-initialization if I'm reading > cppref correctly and init of std::array also works. I think this would rather hide programming errors of accidentally passing to few parameters than being convenient. > With this behavior I could use e.g. = T{0} + 2 to initialize both a double > and a vector3d to 2 (, 2, 2, ...) assuming if eigen allowed + in addition to > *... Element-wise addition is supported for Eigen::Array, not for Eigen::Matrix -- we had several discussions about that which I'm not going to repeat here. > What about Vector3d{}? Not initializing is an option but Currently, as we don't have initializer-list constructors, it falls back to the default constructor and I think no initialization is the expected behavior for that. You may consider compiling with EIGEN_INITIALIZE_MATRICES_BY_ZERO if you want (all) your matrices be initialized with 0. If we implement initializer-list constructors, I could agree on making the empty list initialize to 0. to match std::array behavior. But other than that, IMO the only good option for non-matching number of parameters is to fail (if possible at compile time). > For dynamic matrices I suggest emulating behavior of > http://en.cppreference.com/w/cpp/numeric/valarray/valarray For VectorXd{...} I agree -- that's merely an implementation issue. But what about MatrixXd{1,2,3,4}? Shall this be a 1x4 or a 4x1 vector?
Ilja, if you want something that is as compatible as possible with a Scalar, then you should rather use Eigen::Array for which Eigen::Array3d(M_PI) creates an array with all elements initialized to M_PI (need the devel branch). As Christoph said, for linear-algebra objects as Eigen::Vector* or Eigen::Matrix<> this wont be supported because there is no natural behavior. Christoph, Agree to have an empty list initialize to 0. Agree to fail if the number of parameters do not match (expect for Array initialized by a singleton). For 2D objects (e.g., ArrayXXf or MatrixXd), we could request something like {{1,2},{3,4}}. The interpretation should depend on the storage layout, so a MatrixXd initialized with {{1,2},{3,4}} would create: 1 3 2 4 See also the Tensor module for which such a mechanism already exist (though it has to be adapted to follow the storage layout).
(In reply to Gael Guennebaud from comment #7) > Agree to fail if the number of parameters do not match (expect for Array > initialized by a singleton). Ok, for Array it makes sense, since assigning a scalar to an Array is implemented, as well. > For 2D objects (e.g., ArrayXXf or MatrixXd), we could request something like > {{1,2},{3,4}}. The interpretation should depend on the storage layout, so a > MatrixXd initialized with {{1,2},{3,4}} would create: > > 1 3 > 2 4 That would be confusing compared to the comma-initializer, which is always row-major: MatrixXd A(2,2); A << 1,2, 3,4; > See also the Tensor module for which such a mechanism already exist (though > it has to be adapted to follow the storage layout). I'm tending to always make these kinds of initializers follow lexicographic order. And if one really wants different order, this shall be explicitly specified. Generally, I think storage order should only influence low-level functionality, such as .data() and Map<...> (and of course the internal behavior).
> > I would go with standard behavior, so unspecified items would be > > value-initialized which for doubles means zero-initialization if I'm reading > > cppref correctly and init of std::array also works. > I think this would rather hide programming errors of accidentally passing to > few parameters than being convenient. > > With this behavior I could use e.g. = T{0} + 2 to initialize both a double > > and a vector3d to 2 (, 2, 2, ...) assuming if eigen allowed + in addition to > > *... > Element-wise addition is supported for Eigen::Array, not for Eigen::Matrix > -- we had several discussions about that which I'm not going to repeat here. I forgot about Array, I guess I can use it temporarily since it can be assigned to a Vector after the scalar operation. > > What about Vector3d{}? Not initializing is an option but > Currently, as we don't have initializer-list constructors, it falls back to > the default constructor and I think no initialization is the expected > behavior for that. > You may consider compiling with EIGEN_INITIALIZE_MATRICES_BY_ZERO if you > want (all) your matrices be initialized with 0. A preprocessor directive doesn't seem like a good way to go. What about adding another template parameter for allocation/initialization policy? The default value could be what is done now to preserve backwards compatibility. With delegating constructors etc. it should also allow customization of constructor behavior. By changing the policy Eigen containers could leave value(s) uninitialized, etc. > If we implement initializer-list constructors, I could agree on making the > empty list initialize to 0. to match std::array behavior. But other than > that, IMO the only good option for non-matching number of parameters is to > fail (if possible at compile time). > > > For dynamic matrices I suggest emulating behavior of > > http://en.cppreference.com/w/cpp/numeric/valarray/valarray > > For VectorXd{...} I agree -- that's merely an implementation issue. > But what about MatrixXd{1,2,3,4}? Shall this be a 1x4 or a 4x1 vector? As MatrixXd is quite close to e.g. std::vector<std::vector<...>> it might make sense to require {{...}, {...}, ...} for initialization.
> For 2D objects (e.g., ArrayXXf or MatrixXd), we could request something like > {{1,2},{3,4}}. The interpretation should depend on the storage layout, so a > MatrixXd initialized with {{1,2},{3,4}} would create: An easier to remember approach would be to always have e.g. inner most {}s initialize the last or first index, etc. regardless of storage order. This could also be decided by the init policy.
(In reply to Ilja Honkonen from comment #9) > > You may consider compiling with EIGEN_INITIALIZE_MATRICES_BY_ZERO if you > > want (all) your matrices be initialized with 0. > > A preprocessor directive doesn't seem like a good way to go. What about > adding another template parameter for allocation/initialization policy? While I admit that the preprocessor directive is only a hack, I don't really like adding a template parameter for that, either. Mostly, because it only influences the construction but might lead to different instantiations of equivalent code afterwards (cf Bug 416). Btw, an easy solution for your special case would be to inherit from Vector3d (or Matrix<double, N, 1> with templated N) and implement your own custom constructors that fit your need: template<int N> MyVector : public Eigen::Matrix<double, N, 1> { MyVector(const double& value = 0.0) { this->setConstant(value); } MyVector(const std::initializer_list<double>&) {...}; };
-- GitLab Migration Automatic Message -- This bug has been migrated to gitlab.com's GitLab instance and has been closed from further activity. You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.com/libeigen/eigen/issues/954.