seeking to create own point type wrote this:
so first of all using concept to constraint the type
//concept
template<typename T>
concept Numeric = requires(T param)
{
requires std::is_integral_v<T> || std::is_floating_point_v<T>;
requires !std::is_same_v<bool, T>;
requires std::is_arithmetic_v<decltype(param +1)>;
requires !std::is_pointer_v<T>;
};
the basic point template, just a wrapper arround an array
// Point<T,n>
template <Numeric T, size_t dim = 2 >
struct basic_point {
constexpr auto inline copy( basic_point<T,dim> const& p) {
std::copy(p, p + dim * sizeof(p[0]), array.begin());
}
auto inline copy( T const (&p)[dim]) {
std::copy(p, p + dim * sizeof(p[0]), array.begin());
}
auto inline copy( T const& val) noexcept {
for (auto& a : array)
a = val;
}
// new constructor
constexpr basic_point( T const (&pt)[dim]) { copy(pt); }
// copy constructor
constexpr basic_point( basic_point<T,dim> const& p) { copy(p); }
// default constructor
constexpr basic_point( T dt = 0 ) noexcept { copy(dt); }
virtual ~basic_point() = default ;
constexpr auto inline operator+=( basic_point<T,dim> const& o ) noexcept {
for(size_t i = 0; i < dim;i++)
array[i] += o.array[i];
}
constexpr auto inline operator-=( basic_point<T,dim> const& o ) noexcept { for(size_t i = 0; i < dim;i++) array[i] -= o.array[i]; }
friend constexpr inline auto operator+( basic_point<T,dim> const& a, basic_point<T,dim> const& b ) noexcept { basic_point<T,dim> sum{a}; sum += b; return sum; }
friend constexpr inline auto operator-( basic_point<T,dim> const& a, basic_point<T,dim> const& b ) noexcept { basic_point<T,dim> rest{a}; rest -= b; return rest;}
std::array<T,dim> array;
};
A special template then is explicitly managing a 2d point where x and y refer to elements 0 and 1 of the array, using composition, no inheritance.
//Point2D<T>
template<Numeric T = size_t> struct Point2D {
constexpr Point2D(T const (&p)[2]) {
data = p;
x = data.array[0];
y = data.array[1];
}
Point2D(Point2D const& o) : x(o.x),y(o.y){}
void operator+=( Point2D const& other ) {
x += other.x;
y += other.y;
}
void operator-=( Point2D const& other) {
x -= other.x;
y -= other.y;
}
friend Point2D operator+( Point2D const& a, Point2D const& b ) {
Point2D sum( a );
sum += b;
return sum;
}
friend Point2D operator-( Point2D const&a, Point2D const& b ) {
Point2D rest( a );
rest -= b;
return rest;
}
T& x = data.array[0];
T& y = data.array[1];
basic_point<T,2> data = basic_point<T,2>(0);
};
to test it a trivial example can be ran like this
int main(int argc, char* argv[]) {
const int a[2] = { 1 , 3 };
const int b[2] = { 1 , 3 };
auto point_a = Point2D(a);
auto point_b = Point2D(b);
auto result = point_a + point_b;
std::cout << "Result : ("<< result.x << " , " << result.y <<")\n";
return 0;
}
but it compiles and terminates due to access violation. Any idea why is this happening.
You got the pointer arithmetic wrong when you call std::copy
in your basic_point::copy
method which accepts an array (T const (&p)[dim]
).
Instead of:
std::copy(p, p + dim * sizeof(p[0]), array.begin());
It should be:
std::copy(p, p + dim, array.begin());
Because when you use operator+
on a pointer (or an array) it automatically takes into account the sizeof
of the object the pointer/array points to, therefore p + dim
already advances the address by dim
elements of size sizeof(p[0])
.
The access-violation error you get is because you access the array out-of-bounds (due to the wrong end address).
This live demo is a fixed version of the one you posted: Live demo
Another issue which is not triggered by your test is the call the std::copy
in your other basic_point::copy
(the one that accepts a basic_point<T,dim> const& p
). Your code attempts to use p
as if it was a pointer but it is actually a reference (to a point) so it doesn't really makes sense.
I am not sure why this method is even needed, but maybe you meant something like:
std::copy(p.array.begin(), p.array.end(), array.begin());