Inherited std::array and aggregate initialization - c++

I have a need to compare triplets of doubles that were calculated using different processes which causes them to differ by small amounts but should be considered equivalent. One approach that appears to work is to inherit std::array in such a way that the values can be compared within some delta of each other. This appears to work:
template <int precision_equals = 4> // default equal test precision is .1^4 (.0001)
class RGB : public std::array<double,3>
I also need to interop with standard arrays which requires a conversion constructor. However, it appears aggregate initialization is not allowed when a constructor is provided: aggregate initialization.
no user-provided, inherited, or explicit constructors (explicitly defaulted or deleted constructors are allowed)
But I have added this constructor which is needed when assigning from a regular array like b2 = a; in the code:
RGB(const std::array<double,3>& x) {*static_cast<std::array<double,3>*>(this) = x;}
Yet, this seems to work.
RGB<2> b2{{ 1,2,3 }};
Is this not aggregate initialization? Am I missing something?
#include <iostream>
#include <array>
#include <algorithm>
#include <vector>
using std::vector;
using std::array;
using std::cout;
template <int precision_equals = 4> // default equal test precision is .1^4 (.0001)
class RGB : public std::array<double,3>
{
public:
RGB(const std::array<double,3>& x) {*static_cast<std::array<double,3>*>(this) = x;}
friend bool operator==(const RGB& a, const RGB& b)
{
auto resolution = [](int prec)
{
double factor = 1.0;
while (prec--)
factor = factor / 10.0;
return factor;
};
constexpr double delta = resolution(precision_equals);
return a[0] < b[0] + delta && a[0] > b[0] - delta
&& a[1] < b[1] + delta && a[1] > b[1] - delta
&& a[2] < b[2] + delta && a[2] > b[2] - delta;
}
friend bool operator!=(const RGB& a, const RGB& b) { return !(a == b); }
};
int main()
{
// shows vector of inherited arrays can be sorted
vector<RGB<2>> v{ {{1,2.0001,3}}, {{1,2,3}} };
sort(v.begin(), v.end());
array<double, 3> a{ 1,2,3 };
RGB<2> b2{{ 1,2,3 }};
RGB<2> c2{{ 1.001,2,3 }};
RGB<3> b3{{ 1,2,3 }};
RGB<3> c3{{ 1.005,2,3 }};
// comparisons work
cout << "b2==c2: " << (b2 == c2 ? "true\n" : "false\n");
cout << "b3==c3: " << (b3 == c3 ? "true\n" : "false\n");
// assignments to/from regular arrays work
a = b2;
b2 = a;
}
Works in MSVC and GCC. Link to compiler explorer
#LanguageLawyer notes that an assignment conversion operator would remove most of the need for a conversion constructor. Removal of the conversion constructor and replacement by this
RGB& operator=(const std::array<double, 3>& from)
{
//return *this = *static_cast<const RGB*>(&from); // UB
(*this)[0] = from[0]; // ugly version that's not UB
(*this)[1] = from[1];
(*this)[2] = from[2];
return *this;
}
allows the code to compile so my use case is solved. However, the question whether the conversion constructor prohibits aggregate initialization remains.

Calling base constructor should be better
Untested code
RGB(const std::array<double,3>& x) : std::array<double, 3>(x) {}
or a slight rewrite
using BaseRGB = std::array<double,3>;
template <int precision_equals = 4> // default equal test precision is .1^4 (.0001)
class RGB : public BaseRGB {
public:
RGB(const BaseRGB& x) : BaseRGB(x) {}
// or even
using BaseRGB::BaseRGB; // using the constructor directly if you don't set up anything more.

Related

Keep pointers between class members stable when moving

Suppose a class C has two members, M1 and M2, where M1 holds a pointer P that refers to M2.
For every instance X of C the following invariant should hold: X.M1.P points to X.M2.
Is there an idiomatic way to implement this behaviour in C++ without having to implement a move constructor and assignment operator?
I'm asking because it seems to me that conceptually the pointer P should be relative to M1. Non-default move constructors and assignment operators seem like lots of work (especially if there are a few members) for this simple concept.
My specific use-case is similar to the example below (where set is M1, and less is M2). Perhaps my fundamental approach is flawed — is there a better way than having a pointer to Relation in Less?
using Relation = std::vector<std::vector<bool>>;
class C {
public:
C() { /* less = ...; */ }
C(C&&) = default;
C& operator=(C&&) = default;
private:
struct Less {
explicit Less(const Relation* r) : r(r) {}
bool operator()(int i, int j) { return (*r)[i][j]; }
const Relation* r;
};
Relation less;
std::set<int, Less> set{Less(&less)};
};
C a;
std::cout << a.set.key_comp().r == &a.less << std::endl; // true
C b = std::move(a);
std::cout << b.set.key_comp().r == &b.less << std::endl; // false

Debugger-friendly zero-cost named references to specific locations in an array

struct A
{
int a = 1;
short b = 2;
char c = 3;
}
struct B
{
using arr_type = array<A,3>;
char asd = 0;
A a1;
A a2;
A a3;
// is this safe to use to loop trough all 3 elements?
arr_type* p1 = reinterpret_cast<arr_type*>(&a1);
// or maybe this one?
A* p2 = &a1;
};
Can I safely use p1 or p2 to loop from a1...a3 ?
B b;
for (int i = 0; i < 3; i++)
{
cout << p1[i];
cout << p2[i];
}
The reason why it's not a simple array is because I want each "item" to have a proper name.
I could instead use the union approach, but the C++ prohibits anonymous structs (altho this is not a problem for me since MSVC supports this and GCC seems to support it as well);
union E
{
A arr[3];
struct {
A a1;
A a2;
A a3;
};
};
And the following is clearly safe, but it has a 4 byte overhead for each reference. Which I don't like. (Plus the cost to initialize the references..)
struct B
{
char asd;
A arr[3];
A& a1 = arr[0];
A& a2 = arr[1];
A& a3 = arr[2];
};
And this one has no overhead but for my very specific case, it's not good enough.
struct B
{
char asd;
A arr[3];
A& a1() { return arr[0] };
A& a2() { return arr[1] };
A& a3() { return arr[2] };
};
I'm gonna be using those a1, a2, a3 names very often, and it's harder to debug them if they are function calls in visual studio. And again, I'm going to be using those fields a lot, so I want to be able to check their values easily.
struct B
{
using arr_type = array<A,3>;
char asd = 0;
A a1;
A a2;
A a3;
// is this safe to use to loop trough all 3 elements?
arr_type* p1 = reinterpret_cast<arr_type*>(&a1);
};
Structs need to align naturally for their types, and so do arrays, but I don't know of any rule saying they have to be the same alignment points.
If there were such a rule that struct layout boundaries for members like this and array boundaries will be the same--it would only apply to standard layout structs:
https://stackoverflow.com/a/7189821/211160
All bets would be off if you did something like:
private:
A a1;
A a2;
public:
A a3;
I'd imagine all bets would be off if it contained anything that flipped off the standard layout switch. As it was questionable to start with, I'd say don't even do it then.
(I'd also wonder what kind of differences #pragma pack() would throw in for arrays vs. structs...not that #pragmas are in the standard, I just wonder.)
union E
{
A arr[3];
struct {
A a1;
A a2;
A a3;
};
};
No, arr[N] and aN would not be equivalent. There are some subtle details about how you can use initial sequences in unions for compatible reading in C++...but that's only between structures with compatible sequences. It says nothing about a struct and an array:
Type punning a struct in C and C++ via a union
I'm gonna be using those a1, a2, a3 names very often, and it's harder to debug them if they are function calls in visual studio. And again, I'm going to be using those fields a lot, so I want to be able to check their values easily.
"And the following is clearly safe, but it has a 4 byte overhead for each reference"
In practice it appears you are correct, that today's GCC isn't optimizing it out (per your links):
https://godbolt.org/g/6jAtD5
http://ideone.com/zZqfor
That's disappointing and they could be optimized out, as there's nothing in the standard saying they have to take up space. They point internally to the structure, and they don't change for the lifetime of the structure. :-/
Your complaint against the function access which would be optimized away was that it wasn't debugger-friendly enough. Why not do both?
struct B
{
char asd;
A arr[3];
A& a1() { return arr[0] }
const A& a1() const { return arr[0]; }
A& a2() { return arr[1] };
const A& a2() const { return arr[1]; }
A& a3() { return arr[2] };
const A& a3() const { return arr[2]; }
#if !defined(NDEBUG)
A& a1_debug = arr[0];
A& a2_debug = arr[1];
A& a3_debug = arr[2];
#endif
};
If debugger-friendliness features of projecting your data structures is important to you...it might be a good use of time to learn how to write custom debugger helpers for your environment, e.g.:
http://doc.qt.io/qtcreator/creator-debugging-helpers.html
I guess whether that's worth it depends on how often you have this kind of concern.
No need for such nastiness.
std::tuple coupled with a lambda gives you all the functionality you want. Plus it's perfectly legal, optimal and correct.
If we define a member function that returns a tuple of references to all As in the structure:
auto all_a() const {
return std::tie(a1, a2, a3);
}
...then create a little plumbing for provide a means to walk over the tuple (see below)...
... we can write code like this:
B b;
for_each(b.all_a(),
[](const A& a) { std::cout << a << std::endl; });
Full example (although I didn't implement operator<<, you can do that yourself).
#include<iostream>
#include<array>
#include<tuple>
#include<utility>
using namespace std;
struct A
{
int a = 1;
short b = 2;
char c = 3;
};
std::ostream& operator<<(std::ostream& os, const A& a);
struct B
{
char asd = 0;
A a1;
A a2;
A a3;
auto all_a() const {
return std::tie(a1, a2, a3);
}
};
template<class Tuple, size_t...Is, class F>
void for_each_impl(const Tuple& t, std::index_sequence<Is...>, F&& f)
{
using expand = int[];
void(expand { 0, (void(f(std::get<Is>(t))),0)... });
}
template<class...Ts, class F>
void for_each(const std::tuple<Ts...> ts, F&& f)
{
using expand = int[];
for_each_impl(ts,
std::make_index_sequence<sizeof...(Ts)>(),
std::forward<F>(f));
}
int main()
{
B b;
for_each(b.all_a(),
[](const A& a) { std::cout << a << std::endl; });
}

std::array constructor inheritance

I'm trying to get extended variant of std::array for math vectors (and expose same interface as array does without boilerplate code). I know about std::valarray but I want fixed size for proper typing in matrix multiplications. Thus I array fits perfectly. But when I try to inherit constructor it fails.
struct vec2d : std::array<float, 2>
{ using array::array; }; // simplified
struct vec : std::vector<float>
{ using vector::vector; };
std::array<float, 2> x = {1, 2};
vec y = {1, 2};
vec2d z = {1, 2}; // error: could not convert ‘{1, 2}’
// from ‘<brace-enclosed initializer list>’ to ‘vec2d’
This error reported for GCC 4.8.2 and for clang 3.4. Last says that vec2d have only implicit default/copy/move constructors. Yes, array have only implicit ctor in contrary to vector which have ctor from initializer_list. But since ctors are inherited it is natural to inherit possibility to initialize it in a same way as array initialized.
Question: Why we have that error instead of expected behavior (similar to array initialization)?
Note: I that I can write forwarding manually to make it work, but this doesn't look as elegant as ctor inheritance.
struct vec2d : std::array<float, 2>
{
using array::array;
// nasty boilerplate code I don't want to have in C++11
template <typename... Args>
vec2d(Args &&... args) : array({float(std::forward<Args>(args))...}) {}
};
std::array is designed to be an aggregate, so it intentionally does not define any constructors.
Unfortunately, this means it's not possible to inherit from it and get the same behaviour, as aggregates cannot have base classes.
Why do you need to inherit from std::array anyway? Do you plan to add any private members? If not, then you could just build your framework around free functions operating on std::array, or perhaps a typedef to it.
If you really want to inherit from std::array, you'll have to accept losing the aggregate status and provide any constructors you want yourself.
Note that the answer above applies to C++11 and C++14 only. In C++17, the definition of aggregates was loosened to allow public base classes in them, so simply deriving from std::array and removing the using declaration is enought to make the code compile:
struct vec2d : std::array<float, 2>
{ }; // simplified
std::array<float, 2> x = {1, 2};
vec2d z = {1, 2};
[Live example]
I had exactly the same problem, trying to mimic the behavior of numpy.
The way I solved this was to implement a constructor that takes as argument an std::array<float,N> (with & or && or without anything depending on the needs).
The initializer list is then cast automatically to that type, and the right constructor is then called. To be more concrete:
#include <array>
#include <ostream>
#include <iostream>
using namespace std;
template <int N> class Row: public array<double,N>{
public:
Row<N>(){}
// this is the constructor needed
Row<N>(array<double,N> a) : array<double,N> (a) {}
// or, alternatively,
// Row<N>(array<double,N>&& a) : array<double,N> (a) {}
Row<N>(array<double,N>& a) : array<double,N> (a) {}
// other things that may be relevant
Row<N> operator+(Row<N>& other){
Row<N> result;
for(int i =0; i < N ; ++i){
result[i] = (*this)[i] + other[i]; // notice '*'
}
return result;
}
// for lvalues
template <int n> friend ostream& operator<<(ostream& os, Row<n>& r);
// for rvalues
template <int n> friend ostream& operator<<(ostream& os,Row<n>&& r);
};
// for lvalues
template <int N> ostream& operator<<(ostream& os, Row<N>& r){
for(int i =0; i < N ; ++i) os << r[i] << "\t";
return os;
}
// for rvalues
template <int N> ostream& operator<<(ostream& os, Row<N>&& r){
for(int i =0; i < N ; ++i) os << r[i] << "\t";
return os;
}
int main(){
// here Row(array<double,3>&&) is called
// or Row(array<double,3>)
Row<3> a{{1,2,3}}; // same as Row<3> a({1,2,3});
array<double,3> arr = {1,2,3};
Row<3> b(arr);
cout << a << endl; // a and b are lvalues
cout << b << endl;
cout << (a+b) << endl; // (a+b) is a rvalue
return 0;
}

Pointer Wrapper: dereference operator

I'm pretty new to C++ and as an exercise (and perhaps eventually .Net utility) I'm doing a pointer wrapper (actually in C++/CLI, but this applies to C++ as well). This pointer wrapper (called Apont) currently behaves just like a pointer would, as the test below can show, if lines marked 1. and 2. are commented out:
int main(array<System::String ^> ^args)
{
double ia = 10; double ip = 10;
double *p = &ip; // pointer analogy
Apont<double> ^a =
gcnew Apont<double>(ia); // equivalent to what's below, without errors
a = ~ia;/* 1. IntelliSense: expression must have integral or unscoped enum type
error C2440: '=' : cannot convert from 'double' to 'Utilidades::ComNativos::Apont<T> ^'
error C2171: '~' : illegal on operands of type 'double'*/
Console::WriteLine("ip = {0}; *p = {1}; ia = {2}; !a = {3}", ip, *p, ia, !a);
ia = 20; ip = 20;
Console::WriteLine("ip = {0}; *p = {1}; ia = {2}; !a = {3}", ip, *p, ia, !a);
*p = 30; // pointer analogy
a->Valor = 30; // does exacly what's below, without errors
!a = 30;/* 2. IntelliSense: expression must be a modifiable lvalue
error C2106: '=' : left operand must be l-value */
Console::WriteLine("ip = {0}; *p = {1}; ia = {2}; !a = {3}", ip, *p, ia, !a);
//a->Dispose();
Console::ReadKey();
p = nullptr;
return 0;
}
There are two things I don't like here, marked with 1. and 2. in the code comments, before the lines with errors. The operator~ (see 1.) is defined outside Apont, below:
template<typename T> static Apont<T>^% operator ~(T& valor)
{
return gcnew Apont<T>(valor);
}
I think this one has to be defined outside Apont, but I'm not sure. I cannot understand very well the errors it produces (these are, of course, in the use, not in the definition).
To set the value to which the instance of Apont refers I must use a property (the line marked 2. doesn't work, with errors in the setting usage only), Apont::Valor, which is the equivalent to use *p. What I'd like to do is as I use *p to get or set the value it points to, use !a with the same effect on Apont. Here's Apont::operator!()'s current definition:
T operator !()
{
return Valor;
}
As you can see in 2. (comment in the code, before the respective errors), it doesn't work for setting a value. Maybe I should return a reference? Make another operator with the same name, perhaps outside the class? I tried several options, however, I got similar errors, and came out more confused.
The question is: how can I make an operator that behaves like & (in this case, ~) and one that behaves like * (in this case, !, for dereference, but that behaves like Apont::Valor, whose old definition you can see below)?
property T Valor
{
T get()
{
if (pointer != nullptr)
return *pointer;
else if (eliminado && ErroSeEliminado) // means "disposed && ErrorIfDisposed"
throw gcnew ObjectDisposedException("O objeto já foi pelo menos parcialmente eliminadao.");
else if (ErroSeNulo) // means "ErrorIfNull"
throw gcnew NullReferenceException();
else
return 0;
// don't worry, this is not default behavior, it is returned only if you want to ignore all errors and if the pointer is null
}
void set(T valor)
{
*pointer = valor;
}
}
Let me recap in a new answer for clarity.
Solving the ! operator is easy, as I said in my previous answer, just add a reference.
So for the operator ~, the goal was to have it behave like the & operator and call the constructor of the pointer wrapper class.
I don't think that is possible. It is certainly possible for user defined objects, but I don't think it is possible to overload unary operators for builtin types. So there are three solutions depending on what you prefer:
The first one does exactly what you want, but will break for primitive types:
#include <iostream>
template<typename T>
struct A {
T* payload;
A()
: payload(NULL){}
A(T *ptr)
: payload(ptr) {}
T& operator !(){
return *payload;
}
};
// this will not work for primary types
template<typename T>
A<T> operator ~(T &b){
return A<T>(&b);
}
struct B{
int test;
};
int main(){
B b; b.test = 4;
A<B> a;
a = ~b; // I think this is what you want
std::cerr << (!a).test << std::endl;
// this does not work
//int i = 4;
//A<int> a;
//a = ~i;
}
Second solution: use a compound assignment operator. Pros are the side effects are minimal, cons is this is not very intuitive and might break the nice design you had in mind.
#include <iostream>
template<typename T>
struct A {
T* payload;
A() : payload(NULL){}
T& operator !(){
return *payload;
}
};
template<typename T>
A<T>& operator &=(A<T> &a, T& b){ // should be friend of the above
a.payload = &b;
return a;
}
int main(){
int i = 3;
A<int> a;
a &= i;
std::cerr << !a << std::endl;
}
Third solution: overload the basic assignment operator. This is more intuitive to write but has a lot of side effects:
#include <iostream>
template<typename T>
struct A {
T* payload;
A() : payload(NULL){}
T& operator !(){
return *payload;
}
A<T>& operator = (T & b) {
payload = &b;
return *this;
}
};
int main(){
int i = 3;
A<int> a;
a = i;
std::cerr << !a << std::endl;
}
Someone might have a solution to hijack the operators for primitive types, but i can't think of any simple solution.
If i understood your code correctly, you want the operator ~ to return a copy of the pointer wrapper and the operator ! to act as dereference?
In this case, you can define the unary operator ~ inside the Apont class which calls a copy constructor. And the operator ! has to return a reference indeed if you want to asign a value.
I think the following c++ code defines what you want to do (I renamed Apont to A):
#include <iostream>
template<typename T>
struct A {
T* payload;
A(T *ptr)
:payload(ptr) {}
A(const A&other)
:payload(other.payload) {}
T& operator !(){
return *payload;
}
T* operator ~(){
return payload;
}
};
int main(){
#define PRINT(X) std::cerr << #X << " = " << X << std::endl
int i = 0;
PRINT(i);
A<int> a(&i);
!a = 1;
PRINT(i);
A<int> b = ~a;
!b = 2;
PRINT(i);
}
The output of the code above is:
i = 0
i = 1
i = 2
According to your comments, you said you wanted the operator ! to behave exactly like the wrapped pointer. You can do so, but then the syntax changes and you need to dereference it to assign a new value (because it is a pointer...). ie something like:
#include <iostream>
template<typename T>
struct A {
T* payload;
A(T *ptr): payload(ptr) {}
// this now behaves like accessing the wrapped pointer directly
T*& operator !(){
return payload;
}
};
int main(){
#define PRINT(X) std::cerr << #X << " = " << X << std::endl
int i = 0;
int j = 999;
PRINT(i);
A<int> a(&i);
*(!a) = 1; // note the change of syntax here
PRINT(*!a); // and here
!a = &j; // but now you can change the wrapped pointer through the operator
PRINT(*!a);
}

No implicit conversion in overloaded operator

d1 + 4 works but 4 + d1 doesn't even though 4 can be converted implicitly to a GMan. Why aren't they equivalent?
struct GMan
{
int a, b;
GMan() : a(), b() {}
GMan(int _a) : a(_a), b() {}
GMan(int _a, int _b) : a(_a), b(_b) {}
GMan operator +(const GMan& _b)
{
GMan d;
d.a = this->a + _b.a;
d.b = this->b + _b.b;
return d;
}
};
int main()
{
GMan d1(1, 2), d(2);
GMan d3;
d3 = d1 + 4;
d3 = 4 + d1;
}
A call x + y is translated by the C++ compiler into either of the following two calls (depending on whether x is of class type, and whether such a function exists):
Member function
x.operator +(y);
Free function
operator +(x, y);
Now C++ has a simple rule: no implicit conversion can happen before a member access operator (.). That way, x in the above code cannot undergo an implicit conversion in the first code, but it can in the second.
This rule makes sense: if x could be converted implicitly in the first code above, the C++ compiler wouldn’t know any more which function to call (i.e. which class it belongs to) so it would have to search all existing classes for a matching member function. That would play havoc with C++’ type system and make the overloading rules even more complex and confusing.
This answer is correct. Those points then entail the canonical way of implementing such operators:
struct GMan
{
int a, b;
/* Side-note: these could be combined:
GMan():a(),b(){}
GMan(int _a):a(_a),b(){}
GMan(int _a, int _b):a(_a),b(_b){}
*/
GMan(int _a = 0, int _b = 0) : a(_a), b(_b){} // into this
// first implement the mutating operator
GMan& operator+=(const GMan& _b)
{
// the use of 'this' to access members
// is generally seen as noise
a += _b.a;
b += _b.b;
return *this;
}
};
// then use it to implement the non-mutating operator, as a free-function
// (always prefer free-functions over member-functions, for various reasons)
GMan operator+(GMan _a, const GMan& _b)
{
_a += b; // code re-use
return _a;
}
And so on for other operators.