C++11: VectorT now also accepts non-arithmetic types as Scalar.
This commit is contained in:
@@ -138,11 +138,15 @@ class VectorT {
|
|||||||
* Only for 4-component vectors with division operator on their
|
* Only for 4-component vectors with division operator on their
|
||||||
* Scalar: Dehomogenization.
|
* Scalar: Dehomogenization.
|
||||||
*/
|
*/
|
||||||
template<int D = DIM,
|
template<typename S = Scalar, int D = DIM>
|
||||||
typename = typename std::enable_if<D == DIM>::type,
|
auto homogenized() const ->
|
||||||
typename = decltype(values_[0]/values_[3])>
|
typename std::enable_if<D == 4,
|
||||||
typename std::enable_if<D==4, VectorT>::type
|
VectorT<decltype(std::declval<S>()/std::declval<S>()), DIM>>::type {
|
||||||
homogenized() const {
|
static_assert(D == DIM, "D and DIM need to be identical. (Never "
|
||||||
|
"override the default template arguments.)");
|
||||||
|
static_assert(std::is_same<S, Scalar>::value, "S and Scalar need "
|
||||||
|
"to be the same type. (Never override the default template "
|
||||||
|
"arguments.)");
|
||||||
return VectorT(
|
return VectorT(
|
||||||
values_[0]/values_[3],
|
values_[0]/values_[3],
|
||||||
values_[1]/values_[3],
|
values_[1]/values_[3],
|
||||||
@@ -383,7 +387,11 @@ class VectorT {
|
|||||||
//@{
|
//@{
|
||||||
|
|
||||||
/// compute squared euclidean norm
|
/// compute squared euclidean norm
|
||||||
decltype(values_[0] * values_[0]) sqrnorm() const {
|
template<typename S = Scalar>
|
||||||
|
decltype(std::declval<S>() * std::declval<S>()) sqrnorm() const {
|
||||||
|
static_assert(std::is_same<S, Scalar>::value, "S and Scalar need "
|
||||||
|
"to be the same type. (Never override the default template "
|
||||||
|
"arguments.)");
|
||||||
typedef decltype(values_[0] * values_[0]) RESULT;
|
typedef decltype(values_[0] * values_[0]) RESULT;
|
||||||
return std::accumulate(values_.cbegin() + 1, values_.cend(),
|
return std::accumulate(values_.cbegin() + 1, values_.cend(),
|
||||||
values_[0] * values_[0],
|
values_[0] * values_[0],
|
||||||
@@ -391,38 +399,58 @@ class VectorT {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// compute euclidean norm
|
/// compute euclidean norm
|
||||||
auto norm() const -> decltype(std::sqrt(this->sqrnorm())) {
|
template<typename S = Scalar>
|
||||||
|
auto norm() const ->
|
||||||
|
decltype(std::sqrt(std::declval<VectorT<S, DIM>>().sqrnorm())) {
|
||||||
|
static_assert(std::is_same<S, Scalar>::value, "S and Scalar need "
|
||||||
|
"to be the same type. (Never override the default template "
|
||||||
|
"arguments.)");
|
||||||
return std::sqrt(sqrnorm());
|
return std::sqrt(sqrnorm());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto length() const -> decltype(this->norm()) {
|
template<typename S = Scalar>
|
||||||
|
auto length() const ->
|
||||||
|
decltype(std::declval<VectorT<S, DIM>>().norm()) {
|
||||||
|
static_assert(std::is_same<S, Scalar>::value, "S and Scalar need "
|
||||||
|
"to be the same type. (Never override the default template "
|
||||||
|
"arguments.)");
|
||||||
return norm();
|
return norm();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** normalize vector, return normalized vector
|
/** normalize vector, return normalized vector
|
||||||
*/
|
*/
|
||||||
vector_type& normalize() {
|
template<typename S = Scalar>
|
||||||
*this /= norm();
|
auto normalize() ->
|
||||||
return *this;
|
decltype(*this /= std::declval<VectorT<S, DIM>>().norm()) {
|
||||||
|
static_assert(std::is_same<S, Scalar>::value, "S and Scalar need "
|
||||||
|
"to be the same type. (Never override the default template "
|
||||||
|
"arguments.)");
|
||||||
|
return *this /= norm();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** return normalized vector
|
/** return normalized vector
|
||||||
*/
|
*/
|
||||||
auto normalized() const -> decltype((*this) / this->norm()) {
|
template<typename S = Scalar>
|
||||||
|
auto normalized() const ->
|
||||||
|
decltype(*this / std::declval<VectorT<S, DIM>>().norm()) {
|
||||||
|
static_assert(std::is_same<S, Scalar>::value, "S and Scalar need "
|
||||||
|
"to be the same type. (Never override the default template "
|
||||||
|
"arguments.)");
|
||||||
return *this / norm();
|
return *this / norm();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** normalize vector, return normalized vector and avoids div by zero
|
/** normalize vector, return normalized vector and avoids div by zero
|
||||||
*/
|
*/
|
||||||
template<typename S = typename std::result_of<
|
template<typename S = Scalar>
|
||||||
decltype(&VectorT::norm)(VectorT)>::type>
|
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
sizeof(static_cast<S>(0)) >= 0,
|
sizeof(decltype(
|
||||||
|
static_cast<S>(0),
|
||||||
|
std::declval<VectorT<S, DIM>>().norm())) >= 0,
|
||||||
vector_type&>::type
|
vector_type&>::type
|
||||||
normalize_cond() {
|
normalize_cond() {
|
||||||
static_assert(sizeof(static_cast<decltype(norm())>(0)) >= 0,
|
static_assert(std::is_same<S, Scalar>::value, "S and Scalar need "
|
||||||
"normalize_cond() only works with Scalar types that can "
|
"to be the same type. (Never override the default template "
|
||||||
"be statically casted from 0.");
|
"arguments.)");
|
||||||
auto n = norm();
|
auto n = norm();
|
||||||
if (n != static_cast<decltype(norm())>(0)) {
|
if (n != static_cast<decltype(norm())>(0)) {
|
||||||
*this /= n;
|
*this /= n;
|
||||||
|
|||||||
@@ -176,4 +176,46 @@ TEST_F(OpenMeshVectorTest, size_dim) {
|
|||||||
EXPECT_EQ(2, v2i.dim());
|
EXPECT_EQ(2, v2i.dim());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
class C {
|
||||||
|
public:
|
||||||
|
C() {}
|
||||||
|
C(const C &rhs) { ADD_FAILURE() << "Copy constructor used."; }
|
||||||
|
C(C &&rhs) { ++copy_con; }
|
||||||
|
C &operator= (const C &rhs) {
|
||||||
|
ADD_FAILURE() << "Copy assignemnt used.";
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
C &operator= (C &&rhs) { ++copy_ass; return *this; }
|
||||||
|
|
||||||
|
static int copy_con;
|
||||||
|
static int copy_ass;
|
||||||
|
};
|
||||||
|
|
||||||
|
int C::copy_con = 0;
|
||||||
|
int C::copy_ass = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks two things:
|
||||||
|
* 1) Whether VectorT works with a non-arithmetic type.
|
||||||
|
* 2) Whether move construction and assignment works.
|
||||||
|
*/
|
||||||
|
TEST_F(OpenMeshVectorTest, move_constructor_assignment) {
|
||||||
|
|
||||||
|
C::copy_con = 0;
|
||||||
|
C::copy_ass = 0;
|
||||||
|
|
||||||
|
// Test move assigning.
|
||||||
|
OpenMesh::VectorT<C, 3> x, y;
|
||||||
|
x = std::move(y);
|
||||||
|
EXPECT_EQ(3, C::copy_ass);
|
||||||
|
EXPECT_EQ(0, C::copy_con);
|
||||||
|
|
||||||
|
// Test move constructing.
|
||||||
|
OpenMesh::VectorT<C, 3> z(std::move(x));
|
||||||
|
EXPECT_EQ(3, C::copy_ass);
|
||||||
|
EXPECT_EQ(3, C::copy_con);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user