I have two big C structures used in a C legacy code, and I need to convert from one to another, and the other way around. Something like this :
#include <iostream>
struct A {
int a;
float b;
};
struct B {
char a;
int b;
};
struct C {
A a;
B b;
};
struct D {
int a;
char b;
float c;
};
void CtoD( const C& c, D &d ) {
d.a = c.a.a;
d.b = c.b.a;
d.c = c.a.b;
}
void DtoC( const D &d, C& c ) {
c.a.a = d.a;
c.b.a = d.b;
c.a.b = d.c;
}
int main()
{
C c = { { 1, 3.3f }, { 'a', 4 } };
D d = { 1, 'b', 5.5f };
#if 0
CtoD( c, d );
#else
DtoC( d, c );
#endif
std::cout<<"C="<<c.a.a<<" "<<c.a.b<<" "<<c.b.a<<" "<<c.b.b<<std::endl;
std::cout<<"D="<<d.a<<" "<<d.b<<" "<<d.c<<std::endl;
}
Functions CtoD and DtoC are doing the same thing, but in opposite direction. Changing one structure requires changing both of them.
To minimize possibility of an error, and to avoid repetition, I would like to implement some kind of mapping, where I define the connections only once, and then I copy one value to another. This way, only one change is needed if a structure changes.
So, the question is : how to do it? Is there perhaps a design pattern I could use?
My real structures have hundreds of fields. The above is just simplified example.
In your literal example, I don't think it's worth the hassle. Just write tests so that you ensure your conversions work well.
In your real code, if your structs have "hundreds of fields", your structs may be badly designed. Maybe they should be composed of smaller objects. I've never designed anything which required hunderds of fields in exactly the same struct object - instead, these fields allowed some kind of classification so that they could be treated in smaller bunches.
Since your code is legacy and you don't want to rewrite it, just write tests for your conversions functions, as I said above for the example.
Well tested code is no longer legacy code. Legacy code is basically code for which you don't have automated tests.
If rewriting it is not an option, testing it is a must.
About the cost of testing it "both ways", Idan Arye's comment below says everything:
Since the conversion is symmetric, testing it both ways is not that
much more work than testing it one way. All you need to do is init two
structs - C c and D d - and set them to be the converted versions of
each other. Then you just have to check that CtoD(c)==d and
DtoC(d)==c (or use comparison functions if you happen to have them
defined). The big work here is initializing c and d - but you would
have to do that anyways if you wanted to test one way conversion, so
adding the test for the other way is very cheap.
Let's get naughty...
struct rightwards_t {} rightwards;
struct leftwards_t {} leftwards;
template<typename Left, typename Right>
inline void map_field(Left& left, const Right& right, leftwards_t) {
left = right;
}
template<typename Left, typename Right>
inline void map_field(const Left& left, Right& right, rightwards_t) {
right = left;
}
template<typename Direction>
void convert(C& c, D& d, Direction direction) {
map_field(c.a.a, d.a, direction);
map_field(c.b.a, d.b, direction);
map_field(c.a.b, d.c, direction);
}
// Usage
C c;
D d;
convert(c, d, leftwards); // Converts d into c
convert(c, d, rightwards); // Converts c into d
Really don't know if it works (no compiler at hand), but I wanted to write it. If anyone can help me make it correct, please do.
You could do it with a container of hundreds of std::pairs of references to the sub-objects involved. With a references, you can both read and write, so reading from the left-object and writing to the right-object converts one-way. The opposite convert the other way.
Pick your favorite scripting language(if you don't have one yet I recommend Ruby) and write a small script that generate the conversion functions for you(both source and header files).
Unless you pick a lame scripting language, you can even represent the connections directly in the language, when calling the functions that generate the converters. For example, in Ruby after defining generate_converters you could write:
generate_converters :C,:D do
convert 'a.a','a'
convert 'b.a','b'
convert 'a.b','c'
end
I agree with Daniel, not worth the hassle, but you could write a little app that generates the code for you. You feed the app with description of two structs, and bindings between struct members, and the app generates the C code that is then compiled as usual.
Another alternative is to fiddle with pointers to members, but that could consume even more developer's time, so is even less worth the hassle than the first option.
It took me a while to figure out how to do this. And I came out with next solution :
#include <iostream>
#include <algorithm>
#include <cstring>
struct A {
int a;
float b;
};
struct B {
char a;
int b;
};
struct C {
A a;
B b;
};
struct D {
int a;
char b;
float c;
};
template< typename T1, typename T2 >
struct DataField
{
static inline void Update( const T1 & src, T2 & dst ) { dst = src; }
static inline void Update( T1 & dst, const T2 & src ) { dst = src; }
};
template<>
struct DataField< const char*, char* >
{
static inline void Update( const char* src, char* dst ) { strcpy( dst, src ); }
};
template<>
struct DataField< char*, const char* >
{
static inline void Update( char* dst, const char* src ) { strcpy( dst, src ); }
};
template< typename T1, typename T2, int N >
struct DataField< T1[N], T2[N] >
{
static inline void Update( const T1 (&src)[N], T2 (&dst)[N] ) { std::copy_n( src, N, dst ); }
static inline void Update( T1 (&dst)[N], const T1 (&src)[N] ) { std::copy_n( src, N, dst ); }
};
template< typename T1, typename T2 >
void UpdateDataField( T1 & src, T2 & dst )
{
DataField< T1, T2 >::Update( src, dst );
}
template< typename T1, typename T2 >
void UpdateMappedDataFields( T1 & src, T2 & dst )
{
UpdateDataField( src.a.a, dst.a );
UpdateDataField( src.a.b, dst.c );
UpdateDataField( src.b.a, dst.b );
}
void CtoD( const C& c, D &d ) {
UpdateMappedDataFields( c, d );
}
void DtoC( const D &d, C& c ) {
UpdateMappedDataFields( c, d );
}
int main()
{
C c = { { 1, 3.3f }, { 'a', 4 } };
D d = { 1, 'b', 5.5f };
#if 0
CtoD( c, d );
#else
DtoC( d, c );
#endif
std::cout<<"C="<<c.a.a<<" "<<c.a.b<<" "<<c.b.a<<" "<<c.b.b<<std::endl;
std::cout<<"D="<<d.a<<" "<<d.b<<" "<<d.c<<std::endl;
}
All data fields mapping is done in the UpdateMappedDataFields function, and only there.
What I don't like is that the function UpdateMappedDataFields is a template, and the way it is implemented, it prevents autocomplete when using IDEs, since the types are not known.
However, I would still like to hear if there is a better way.
Similar to what Idan and Dialecticus proposed, you can also just use your editor's search and replace function:
E.g. write CtoD manually, copy the body to DtoC and - in eclipse - use
Find: ^(.*)=(.*);
Replace: $2=$1;
in order to automatically swap the left and right side of each assignment in the body of DtoC.
Whether or not this is preferable to the usage of more or less complex c++ constructs depends on your specific code and requirements. In my opinion, the code is easier to read and maintain this way, but of course nothing enforces coherency between CtoD and DtoC after future changes (I'd mention the procedure in a code comment).
Related
This problem is related to Workaround for resizing Eigen::Ref, however, I do not have the restriction of trying to avoid templates (in-fact, I would like to have a solution working with templates)
I'm using the the eigen library (version 3.2.9, but testet with the latest version of eigen as well with the same outcome) for some automatic differentiation (AD) calculations and came across this "bug", which is already known to the developers (see also the following bug reports: Bug report 1, Bug report 2 and Bug report 3).
TL;DR: It is not really a bug, but a generic and clean workaround would likely require some extensive work and since it is not supported by Eigen, not pursued (I guess ...). For me, I am only interested in a subset for of expression for which to get it to work (at least for now) for which there might be a acceptable workaround.
The problem is the following, consider this simplified code, where we have a fixed and dynamic matrix sized AD type
#include <Eigen/Core>
#include "unsupported/Eigen/src/AutoDiff/AutoDiffScalar.h"
typedef Eigen::AutoDiffScalar<Eigen::Matrix<double, -1, 1>> T_dynamic;
typedef Eigen::AutoDiffScalar<Eigen::Matrix<double, 40, 1>> T_fixed;
int main() {
const T_fixed fixed = 10.0;
const T_dynamic dynamic = 100.0;
const auto result = fixed - dynamic;
return 0;
}
This works great. When we hit fixed - dynamic, Eigen will call first the overloaded operator- which looks at both left and right hand side and resizes the derivatives accordingly through the make_coherent_impl() method, which is a template specialised version of make_coherent()
template<typename OtherDerType>
inline const AutoDiffScalar<CwiseBinaryOp<internal::scalar_difference_op<Scalar>, const DerType,const typename internal::remove_all<OtherDerType>::type> >
operator-(const AutoDiffScalar<OtherDerType>& other) const
{
internal::make_coherent(m_derivatives, other.derivatives());
return AutoDiffScalar<CwiseBinaryOp<internal::scalar_difference_op<Scalar>, const DerType,const typename internal::remove_all<OtherDerType>::type> >(
m_value - other.value(),
m_derivatives - other.derivatives());
}
// resize a to match b is a.size()==0, and conversely.
template<typename A, typename B>
void make_coherent(const A& a, const B&b)
{
make_coherent_impl<A,B>::run(a.const_cast_derived(), b.const_cast_derived());
}
template<typename A_Scalar, int A_Rows, int A_Cols, int A_Options, int A_MaxRows, int A_MaxCols, typename B>
struct make_coherent_impl<Matrix<A_Scalar, A_Rows, A_Cols, A_Options, A_MaxRows, A_MaxCols>, B> {
typedef Matrix<A_Scalar, A_Rows, A_Cols, A_Options, A_MaxRows, A_MaxCols> A;
static void run(A& a, B& b) {
if((A_Rows==Dynamic || A_Cols==Dynamic) && (a.size()==0))
{
a.resize(b.size());
a.setZero();
}
}
};
This works, because both types A and B are of Eigen::Matrix<...> type (there are other permutations of the make_coherent_impl() version which is omitted here).
However, consider the following slightly modified example:
#include <Eigen/Core>
#include "unsupported/Eigen/src/AutoDiff/AutoDiffScalar.h"
typedef Eigen::AutoDiffScalar<Eigen::Matrix<double, -1, 1>> T_dynamic;
typedef Eigen::AutoDiffScalar<Eigen::Matrix<double, 40, 1>> T_fixed;
int main() {
const double scalar = 1.0;
const T_fixed fixed = 10.0;
const T_dynamic dynamic = 100.0;
const auto result = dynamic * scalar - fixed * scalar;
return 0;
}
now, when we hit dynamic * scalar - fixed * scalar and go through the the make_coherent() method, we call
template<typename A, typename B>
struct make_coherent_impl {
static void run(A&, B&) {}
};
instead, as A and B are no longer of type Eigen::matrix<...> but rather a CwiseUnaryOp<Operation, DerivativeType>.
This type is again a matrix in the end and I want to resize it, but when doing so, eigen detects that it is not a matrix type and calls a no-op resize function (in the DenseBase.h), as it only allows to resize matrices and arrays (see also the function description, here the CwiseUnaryOp is an expression)
/** Only plain matrices/arrays, not expressions, may be resized; therefore the only useful resize methods are
* Matrix::resize() and Array::resize(). The present method only asserts that the new size equals the old size, and does
* nothing else.
*/
void resize(Index newSize)
{
EIGEN_ONLY_USED_FOR_DEBUG(newSize);
eigen_assert(newSize == this->size() && "DenseBase::resize() does not actually allow to resize.");
}
The partially specialised template version I am using to call the resize function is as follows
template<class UnaryOpLhs, class DerTypeLhs, class UnaryOpRhs, class DerTypeRhs>
struct make_coherent_impl<Eigen::CwiseUnaryOp<UnaryOpLhs, DerTypeLhs>, Eigen::CwiseUnaryOp<UnaryOpRhs, DerTypeRhs> >
{
typedef Eigen::CwiseUnaryOp<UnaryOpLhs, DerTypeLhs> A;
typedef Eigen::CwiseUnaryOp<UnaryOpRhs, DerTypeRhs> B;
static void run(A& a, B& b) {
if(a.size()==0 && b.size()!=0)
a.resize(b.size());
else if(b.size()==0 && a.size()!=0)
b.resize(a.size());
}
};
Is there a way to cast the CwiseUnaryOp to a matrix so we can resize it again or a different route that would achieve the same thing here? I am only showing CwiseUnaryOp here but it should work equally for CwiseBinaryOp
Some background on what I try to do:
I am trying to implement a library doing quantum mechanics. As quantum mechanics is basically just linear algebra, I'm using the armadillo linear algebra library underneath. Armadillo uses lazy evaluation to do some smart tricks with matrices, which gives a pretty good abstraction from what is actually going on and looks close to matlab code.
I want to do something similar, but I also want to be able to use auto, which is not possible with armadillo (or eigen).
I have been looking around a little, and this answer contains what I think is the typical way of implementing this: https://stackoverflow.com/a/414260/6306265
The problem with this approach is that when you write
auto C = A+B;
you get a C that is a matrix_add, not a matrix. Even if matrix_add behaves similarly enough to matrix, the fact that matrix_add contains references to A and B makes it awkward to carry around. E.g.
auto A = matrix(2,2,{0,1,0,1});
auto B = matrix(2,2,{1,0,1,0});
auto C = A+B;
C.printmatrix(); // 1,1 ; 1,1
but
auto A = matrix(2,2,{0,1,0,1});
auto B = matrix(2,2,{1,0,1,0});
auto C = A+B;
A(0,0) = 1;
C.printmatrix(); // 2,1 ; 1,1
which is counter-intuitive. As mathematically intuitive behaviour is what I want to achieve, that is a problem.
Even worse is when I do
auto sumMatrices(const matrix& A, const matrix& B)
{
return A+B;
}
which returns a matrix_add with references to local memory.
I would really like to be able to have the nice, overloaded behaviour but also be able to use auto. My idea was to make a wrapper that can hold either a reference or an instance:
template<class T>
class maybe_reference
{
public:
maybe_reference(const T& t):
ptr_(std::make_unique<T>(t)),
t_(*ptr_)
{}
maybe_reference(std::reference_wrapper<const T> t):
t_(t.get())
{}
const T& get(){return t_;}
private:
unique_ptr<T> ptr_;
const T& t_;
}
It may not be implemented exactly this way, but the general idea is to have two constructors that can be clearly distinguished to ensure that get() returns either the referenced object or the one in the unique_ptr.
Modified matrix_add:
class matrix_add {
public:
friend matrix_add operator+(const matrix& A, const matrix& B);
matrix_add(matrix_add&& other): A_(other.A_.get()), B_(other.B_.get()){}
private:
matrix_add(const matrix& A, const matrix& B): A_(std::ref(A)), B_(std::ref(B)){}
maybe_reference<matrix> A_;
maybe_reference<matrix> B_;
};
I have left out all the parts that make matrix_add behave like a matrix. The idea is to have the object refer to the outside objects A&B as long as it was constructed with A+B, but when it is move-constructed, it would own copies.
My question is basically: does this work?
I have been thinking that the move-constructor may be elided in some or all cases, which might be devastating.
Also, is there an alternative to achieve the same thing? I have been looking, but it seems that for linear algebra at least its either lazy or auto.
EDIT: Thanks to being reminded of the term "expression templates", my google search was a lot more fruitful. I found this reddit-post: https://www.reddit.com/r/cpp/comments/4puabu/news_about_operator_auto/
and the referenced papers, which allow specification of "casts" to auto. That would be the feature that really would make all of this work.
I think, your basic problem is, that lazy evaluation does not mix well with changing state. I see two possible routes out of this:
Make your matrices immutable. If you "modify" a matrix, you actually create a copy with the incorporated change, the original remains intact. This works well semantically (any math works exactly as you expect it to do), however it may incur an intolerable runtime overhead if you are setting your matrices value by value.
This allows your implementation of matrix_add to silently replace itself with a matrix object when it is evaluated, ensuring that each evaluation is only performed at most once.
Make your functions explicit. Don't create matrix_add objects that act as if they were matrices themselves, but create matrix_function objects that operate on some input matrices to yield some result. This allows you to explicitly perform the evaluation where you see fit, and to reuse the functions that you define. However, this approach will lead to a lot of additional code complexity.
I don't think it's a good idea to try to work around this problem by introducing implicit points of forced evaluation: You'll loose large parts of what can be achieved by lazy evaluation, so why bother in the first place? Just my two cents.
You could write a template function evaluate which by default is a NOP, and then overload as necessary.
#include <utility>
#include <type_traits>
struct matrix {};
struct matrix_add {
matrix operator()() const;
};
matrix_add operator + (matrix const& a, matrix const& b);
template<class T> decltype(auto) evaluate(T&& val) { return std::forward<T>(val); }
matrix evaluate(matrix_add const& lazy) { return lazy(); }
matrix evaluate(matrix_add & lazy) { return lazy(); }
matrix evaluate(matrix_add && lazy) { return lazy(); }
int main()
{
auto a = matrix();
auto b = matrix();
auto c = evaluate(a + b);
auto d = evaluate(1 + 2);
static_assert(std::is_same<decltype(c), matrix>::value, "");
static_assert(std::is_same<decltype(d), int>::value, "");
}
I will define a new operator: eager_eval, like this:
namespace lazy {
template<class T>
void eager_eval(T const volatile&)=delete;
template<class T>
struct expression {
template<class D,
std::enable_if_t<std::is_base_of<expression, std::decay_t<D>>{}, int> =0
>
friend T eager_eval( D&& d ) { return std::forward<D>(d); }
};
}
Whenever you want something to be evaluatable in an eager manner, define eager_eval in its namespace, or derive it from lazy::lazy_expression<target_type>.
So we modify your matrix_add to (A) derive from it with the lazy-produced type you want, and (B) have an operator matrix:
struct matrix_add:
lazy::expression<matrix>
{
matrix_add(matrix const& a, matrix const& b) : a(a), b(b) { }
operator matrix() && { // rvalue ref qualified as it should be.
matrix result;
// Do the addition.
return result;
}
private:
matrix const& a, b;
};
and now, anyone can do:
auto e = eager_eval( a+b );
and ADL finds the right type to eager evaluate the lazy expression to.
live example.
You could, optionally, implement a default eager_eval that returns its argument:
template<class T, class...Ts>
T eager_eval(T&& t, Ts&&...) { return std::forward<T>(t); }
then
using lazy::eager_eval;
auto x = eager_eval( 1+2 );
lets you be agnostic to the type you pass to eager_eval; if it is a type that is aware of being lazy via an eager_eval overload, it converts, and if not it does not convert.
The pack in lazy::eager_eval above is to ensure that it has the lowest priority as an overload.
with c++17 class template argument deduction, you may write
struct matrix_expr_foo {};
struct matrix_expr_bar {};
template< typename L, typename R >
struct matrix_add {
// ...
};
matrix_add<matrix_expr_foo,matrix_expr_bar> operator + (matrix_expr_foo const& a, matrix_expr_bar const& b);
template< typename T >
struct expr {
expr( T const& expr ){
// evaluate expr ( to be stored in an appropriate member )
}
// ...
};
int main()
{
auto a = matrix_expr_foo();
auto b = matrix_expr_bar();
expr c = a + b;
/* different naming ?
auto_ c = a + b;
...
*/
}
where expr is meant to act as an auto for expression templates ...
I've recently run into a quite a few situations where the Named Parameter Idiom would be useful, but I'd like it to be guaranteed in compile-time. The standard method of returning references in a chain almost always appears to invoke a run-time constructor (compiling with Clang 3.3 -O3).
I haven't been able to find anything with reference to this so I tried to get this to work with constexpr and got something functional:
class Foo
{
private:
int _a;
int _b;
public:
constexpr Foo()
: _a(0), _b(0)
{}
constexpr Foo(int a, int b)
: _a(a), _b(b)
{}
constexpr Foo(const Foo & other)
: _a(other._a), _b(other._b)
{}
constexpr Foo SetA(const int a) { return Foo(a, _b); }
constexpr Foo SetB(const int b) { return Foo(_a, b); }
};
...
Foo someInstance = Foo().SetB(5).SetA(2); //works
While this is okay for a small number of parameters, for larger numbers it quickly blows up into a mess:
//Unlike Foo, Bar takes 4 parameters...
constexpr Bar SetA(const int a) { return Bar(a, _b, _c, _d); }
constexpr Bar SetB(const int b) { return Bar(_a, b, _c, _d); }
constexpr Bar SetC(const int c) { return Bar(_a, _b, c, _d); }
constexpr Bar SetD(const int d) { return Bar(_a, _b, _c, d); }
Is there a better way? I'm looking at doing this with classes that have many (30+) parameters and this seems like it would be prone to error if extended in the future.
EDIT: Removed C++1y tag -- while C++1y does appear to fix the problem (thanks TemplateRex!) this is for production code, and we are stuck with C++11. If that means its impossible, then I guess that's just the way it is.
EDIT2: To show why I'm looking for this, here's a use case. Currently with our platform, developers need to explicitly set bit vectors for hardware configurations, and while this is okay it's very error prone. Some are using designated initializers from the C99 extension, which is okay but non-standard:
HardwareConfiguration hardwareConfig = {
.portA = HardwareConfiguration::Default,
.portB = 0x55,
...
};
Most, however, aren't even using this, and are just inputting a blob of numbers. So as a working improvement, I'd like to move towards something like this (since it also forces better code):
HardwareConfiguration hardwareConfig = HardwareConfiguration()
.SetPortA( Port().SetPolarity(Polarity::ActiveHigh) )
.SetPortB( Port().SetPolarity(Polarity::ActiveLow) );
Which might be far more verbose, but much clearer when reading later.
Using Template Metaprogramming
Here is something I came up with to solve your problem (at least partially). By using template metaprogramming, you can leverage the compiler to do most of the job for you. These techniques look weird for those who have never seen such code before, but thankfully most of the complexity can be hidden away in a header and the users only interact with the library in a neat and terse manner.
A Sample Class Definition and its Use
Here is an example of what defining a class would entail on your part:
template <
//Declare your fields here, with types and default values
typename PortNumber = field<int, 100>,
typename PortLetter = field<char, 'A'>
>
struct MyStruct : public const_obj<MyStruct, PortNumber, PortLetter> //Derive from const_obj like this, passing the name of your class + all field names as parameters
{
//Your setters have to be declared like this, by calling the Set<> template provided by the base class
//The compiler needs to be told that Set is part of MyStruct, probably because const_obj has not been instantiated at this point
//in the parsing so it doesn't know what members it has. The result is that you have to use the weird 'typename MyStruct::template Set<>' syntax
//You need to provide the 0-based index of the field that holds the corresponding value
template<int portNumber>
using SetPortNumber = typename MyStruct::template Set<0, portNumber>;
template<int portLetter>
using SetPortLetter = typename MyStruct::template Set<1, portLetter>;
template<int portNumber, char portLetter>
using SetPort = typename MyStruct::template Set<0, portNumber>
::MyStruct::template Set<1, portLetter>;
//You getters, if you want them, can be declared like this
constexpr int GetPortNumber() const
{
return MyStruct::template Get<0>();
}
constexpr char GetPortLetter() const
{
return MyStruct::template Get<1>();
}
};
Using the Class
int main()
{
//Compile-time generation of the type
constexpr auto myObject =
MyStruct<>
::SetPortNumber<150>
::SetPortLetter<'Z'>();
cout << myObject.GetPortNumber() << endl;
cout << myObject.GetPortLetter() << endl;
}
Most of the job is done by the const_obj template. It provides a mechanism to modify your object at compile time. Much like a Tuple, the fields are accessed with 0-based indices but this does not stop you from wrapping the setters with friendly names, as is done with SetPortNumber and SetPortLetter above. (They just forward to Set<0> and Set<1>)
About Storage
In the current implementation, after all the setters have been called and the object declared, the fields end up being stored in a compact array of const unsigned char's named data in the base class. If you use fields that are not unsigned chars (as in done above with PortNumber for example) the field is divided in big endien unsigned char's (could be changed to little endien as needed). If you don't need an actual storage that has an actual memory address, you could omit it altogether by modifying the packed_storage (see full implementation link below) and the values would still be accessible at compile time.
Limitations
This implementation only allows integral types to be used as fields (all flavors of shorts, ints, longs, bool, char). You can still provide setters that act on more than one field though. Example:
template<int portNumber, char portLetter>
using SetPort = typename MyStruct::template Set<0, portNumber>::
MyStruct::template Set<1, portLetter>;
Full Code
The full code for the implementation of this little library can be found here:
Full Implementation
Additional Notes
This code has been tested and works with the C++11 implementation of both g++ and clang.
It has not been tested for hours and hours so of course there may be bugs but it should provide you with a good base to start with. I hope this helps!
In C++14, constraints on constexpr function will be relaxed, and the usual chaining of reference-returning setters will work at compile-time:
#include <iostream>
#include <iterator>
#include <array>
#include <utility>
class Foo
{
private:
int a_ = 0;
int b_ = 0;
int c_ = 0;
int d_ = 0;
public:
constexpr Foo() = default;
constexpr Foo(int a, int b, int c, int d)
:
a_{a}, b_{b}, c_{c}, d_{d}
{}
constexpr Foo& SetA(int i) { a_ = i; return *this; }
constexpr Foo& SetB(int i) { b_ = i; return *this; }
constexpr Foo& SetC(int i) { c_ = i; return *this; }
constexpr Foo& SetD(int i) { d_ = i; return *this; }
friend std::ostream& operator<<(std::ostream& os, const Foo& f)
{
return os << f.a_ << " " << f.b_ << " " << f.c_ << " " << f.d_ << " ";
}
};
int main()
{
constexpr Foo f = Foo{}.SetB(5).SetA(2);
std::cout << f;
}
Live Example using Clang 3.4 SVN trunk with std=c++1y.
I'm not sure if classes with 30 parameters are a good idea (Single Responsiblity Principle and all that) but at least the above code scales linearly in the number of setters, with only 1 argument per setter. Note also that there are only 2 constructors: the default one (which takes its arguments from the in-class initializers) and the full one which takes 30 ints in your ultimate case).
I have several different C++ structs and classes with fields of the same name, that I have to copy between frequently. I would like to do something like: (in bashy pseudocode)
struct S{double a;
double b;
double c;};
class C{public: void set_a(double a);
void set_b(double b);
void set_c(double c); };
S s; C c;
#FOR F in FIELDSOF(S)
c.set_${F}(${F});
#ENDFOR
Whether or not it a good idea, is there a way to abuse either the C++ preprocessor or C++ templates to achieve this? I use g++ and clang++.
I am already aware of templating engines like MAKO, and I'm also aware I could write a program to do code generation. If you must know, one of the things I would like to use this for is filling Google protobufs from C++ structs.
If you already have a Boost dependency, you can use BOOST_FUSION_ADAPT_STRUCT and use Fusion to iterate over the members. This also allows you to work with types, which is not possible in a pure preprocessor approach.
You also will need to map member functions to fusion sequences to make that more automatic.
All in all: Just write a constructor.
See this answer, which shows how to iterate over the members of a class. Then using those macros, the two classes can be reflectable like this:
struct S
{
REFLECTABLE
(
(double) a,
(double) b,
(double) c
)
};
class C
{
private:
REFLECTABLE
(
(double) a,
(double) b,
(double) c
)
public:
void set_a(double a);
void set_b(double b);
void set_c(double c);
};
Then to create a generic assignment, based on the name of the member variable:
struct assign_fields_visitor
{
template<class FieldData1, class FieldData2>
void operator()(FieldData1 fd1, FieldData2 fd2)
{
if (strcmp(fd1.name(), fd2.name()) == 0)
{
fd1.get() = fd2.get();
}
}
};
struct assign_fields
{
template<class X, class FieldData>
void operator()(X & x, FieldData f)
{
visit_each(x, boost::bind(assign_fields_visitor(), f, _1));
}
};
template<class L, class R>
void assign(L & lhs, const R& rhs)
{
visit_each(rhs, boost::bind(assign_fields(), boost::ref(lhs), _1));
}
Finally, it can be called like this:
S s; C c;
assign(c, s);
I have a struct that's defined like this:
struct Vec3 {
float x, y, z;
}
When I attempted to use std::unique on a std::vector<Vec3>, I was met with this error:
Description Resource Path Location Type
no match for ‘operator==’ in ‘_first._gnu_cxx::__normal_iterator<_Iterator, _Container>::operator* with _Iterator = Vec3*, _Container = std::vector > == _next._gnu_cxx::__normal_iterator<_Iterator, _Container>::operator* with _Iterator = Vec3*, _Container = std::vector >’ ModelConverter line 4351, external location: /usr/include/c++/4.4.6/bits/stl_algo.h C/C++ Problem
I understand the the necessity of the naievite of the compiler in inequality operators and others (in this case, * would almost certainly not be what I mean), but is this a matter of policy, or is there a technical reason for it that I'm not aware of? There's a default assignment operator, so why no default equality operator?
There's no technical reason. Pedantically, you might say this is because C doesn't let you compare two structures with ==, and this is a good reason; that behavior switching when you go to C++ is non-obvious. (Presumably, the reason that C doesn't support that is that field-wise comparison might work for some structs, but definitely not all.)
And just from a C++ point of view, what if you have a private field? A default == technically exposes that field (indirectly, but still). So would the compiler only generate an operator== if there are no private or protected data members?
Also, there are classes that have no reasonable definition of equality (empty classes, classes that do not model state but cache it, etc.), or for whom the default equality check might be extremely confusing (classes that wrap pointers).
And then there's inheritance. Deciding what to do for operator== in a situation of inheritance is complicated, and it'd be easy for the compiler to make the wrong decision. (For example, if this was what C++ did, we would probably be getting questions about why == always succeed when you test equality between two objects that are both descendants of an abstract base class and being used with a reference to it.)
Basically, it's a thorny problem, and it's safer for the compiler to stay out of it, even considering that you could override whatever the compiler decided.
The question of why you have to provide operator== is not the same as the question of why you have to provide some comparison function.
Regarding the latter, the reason that you are required to provide the comparison logic, is that element-wise equality is seldom appropriate. Consider, for example, a POD struct with an array of char in there. If it’s being used to hold a zero-terminated string, then two such structs can compare unequal at the binary level (due to arbitrary contents after the zero bytes in the strings) yet being logically equivalent.
In addition, there are all the C++ level complications mentioned by other answers here, e.g. the especially thorny one of polymorphic equality (you really don’t want the compiler to choose!).
So, essentially, there is simply no good default choice, so the choice is yours.
Regarding the former question, which is what you literally asked, why do you have to provide operator==?
If you define operator< and operator==, then the operator definitions in namespace std::rel_ops can fill in the rest for you. Presumably the reason why operator== is needed is that it would be needlessly inefficient to implement it in terms of operator< (then requiring two comparisons). However, the choice of these two operators as basis is thoroughly baffling, because it makes user code verbose and complicated, and in some cases much less efficient than possible!
The IMHO best basis for comparison operators is instead the three-valued compare function, such as std::string::compare.
Given a member function variant comparedTo, you can then use a Curiously Recurring Template Pattern class like the one below, to provide the full set of operators:
template< class Derived >
class ComparisionOps
{
public:
friend int compare( Derived const a, Derived const& b )
{
return a.comparedTo( b );
}
friend bool operator<( Derived const a, Derived const b )
{
return (compare( a, b ) < 0);
}
friend bool operator<=( Derived const a, Derived const b )
{
return (compare( a, b ) <= 0);
}
friend bool operator==( Derived const a, Derived const b )
{
return (compare( a, b ) == 0);
}
friend bool operator>=( Derived const a, Derived const b )
{
return (compare( a, b ) >= 0);
}
friend bool operator>( Derived const a, Derived const b )
{
return (compare( a, b ) > 0);
}
friend bool operator!=( Derived const a, Derived const b )
{
return (compare( a, b ) != 0);
}
};
where compare is an overloaded function, e.g. like this:
template< class Type >
inline bool lt( Type const& a, Type const& b )
{
return std::less<Type>()( a, b );
}
template< class Type >
inline bool eq( Type const& a, Type const& b )
{
return std::equal_to<Type>()( a, b );
}
template< class Type >
inline int compare( Type const& a, Type const b )
{
return (lt( a, b )? -1 : eq( a, b )? 0 : +1);
}
template< class Char >
inline int compare( basic_string<Char> const& a, basic_string<Char> const& b )
{
return a.compare( b );
}
template< class Char >
inline int compareCStrings( Char const a[], Char const b[] )
{
typedef char_traits<Char> Traits;
Size const aLen = Traits::length( a );
Size const bLen = Traits::length( b );
// Since there can be negative Char values, cannot rely on comparision stopping
// at zero termination (this can probably be much optimized at assembly level):
int const way = Traits::compare( a, b, min( aLen, bLen ) );
return (way == 0? compare( aLen, bLen ) : way);
}
inline int compare( char const a[], char const b[] )
{
return compareCStrings( a, b );
}
inline int compare( wchar_t const a[], wchar_t const b[] )
{
return compareCStrings( a, b );
}
Now, that’s the machinery. What does it look like to apply it to your class …
struct Vec3
{
float x, y, z;
};
?
Well it’s pretty simple:
struct Vec3
: public ComparisionOps<Vec3>
{
float x, y, z;
int comparedTo( Vec3 const& other ) const
{
if( int c = compare( x, other.x ) ) { return c; }
if( int c = compare( y, other.y ) ) { return c; }
if( int c = compare( z, other.z ) ) { return c; }
return 0; // Equal.
}
};
Disclaimer: not very tested code… :-)
C++20 adds this capability:
struct Vec3 {
float x, y, z;
auto operator<=>(const Vec3&) const = default;
bool operator==(X const&) const = default;
}
This is currently only implemented in GCC and clang trunk. Note that currently defaulting operator<=> is equivalent to also defaulting operator==, however there is an accepted proposal to remove this. The proposal suggests having defaulting operator<=> also imply (not be equivalent to as it is today) defaulting operator== as an extension.
Microsoft has documentation on this feature at https://devblogs.microsoft.com/cppblog/simplify-your-code-with-rocket-science-c20s-spaceship-operator/.
What would you like the equality operation to be? All the fields the same? It's not gonna make that decision for you.