I roughly got the following setup:
#include <iostream>
using namespace std;
template<typename T>
class Element{
T getX() const;
T getY() const;
private:
T x,y;
std::vector<float> handling_times;
float cost;
};
template<typename T, typename Tnext>
class Bloc {
T getX() const;
T getY() const;
private:
T x,y;
Tnext num_blocs;
float effort;
float damage_done;
};
template<typename T>
class Measurements {
void calcMeasurements(const std::vector<T*> &data);
float getMean() const;
private:
float mean;
};
int main() {
std::vector<Element<int>*> elements;
// fill with elements
std::vector<Bloc<float,2>*> blocs;
// fill with blocs
// calculate mean of blocs effort
Measurements<Bloc<float,1>> bloc_mean_effort_measurement;
bloc_mean_effort_measurement.calcMeasurements(blocs);
return 0;
}
So two classes Element and Bloc which hold some data I'd like to perform Measurements on. For example, I'd like to measure the getMean() of an Element's handling_times which is of type std::vector<float>. Another case would be to measure the mean of std::vector<Bloc<float>*> blocs based on the effort stored in each Bloc. As you can see the input types for an Measurement vary but the functionality behind the mean calculation always stays the same. I'd like to have this functionality only implemented once (mean is only the simplest example I could think of) and use it on different types. Furthermore, I can't get my head around, how to pass the Measurement object based on which entity (e.g. Element costs or Bloc effort) the measure should be computed. Would it make sense to have an enum PossibleMeasurements in Element with HANDLING_TIMES and COSTS. So to say for each private variable I would like to be able to compute measures on.
If I understand the question correclty, you have more or less this:
struct A {
std::vector<int> a;
};
struct B {
int value;
B(int x) : value(x) {}
};
typedef std::vector<B> Bvect;
And now you want to calculate the mean of the values with the same generic function whether they are in an A or in a Bvect. This generic function already exists and is called std::accumulate. For the object containing the vector you would do
A foo;
foo.a.push_back(123);
std::cout << std::accumulate(foo.a.begin(),foo.a.end(),0.0) << "\n";
You have to pass two iterators indicating the first and one past the last element to be accumulated, and an initial value.
For the Bvect it looks quite similar, we just have to supply a custom way of adding up the elements:
Bvect b;
b.push_back(B(123));
std::cout << std::accumulate(b.begin(),
b.end(),
B(0),
[](B b1,B b2){
return B(b1.value + b2.value);
}).value << "\n";
I use a lambda to access the values to be added and construct a B holding the sum of the two values.
PS: This examples only calculate the sum, to get the average simply divide by number of elements.
Related
Suppose I have some class, myClass, with a class constructor that takes 20 arguments, and simply assigns the passed values to class variables. Here's a smaller example, in case that's not clear
class myClass{
float a, b, c;
public:
myClass(float _a, float _b, float _c) : a(_a), b(_b), c(_c) {}
};
Is there a "cleaner" and/or more efficient way to do this? Perhaps a best practice? I've thought about simply passing a vector<float>, something like this:
class myClass{
vector<float> args;
public:
myClass(vector<float> _args){ args = _args; }
};
However, since I'm working with so many parameters, it later becomes confusing. For example, in some method I'm suddenly working with args[13] as opposed to something more descriptive, like numDays. I perform a lot of math on these numbers, so it's important that everything is very clear and concise.
You could write a class that has all these fields and just pass the class. Then, you can do yourClass.numDays and such.
A) The builder pattern
You can use the builder pattern. I am not going to strictly follow the pattern. For official details I refer you to the numerous available online resources on design patterns. The basic idea is that you enable the caller to write instead of
MonsterClass m{ a,b,c, ....... d,e,f };
the nicer
auto m = MonsterBuilder{}.set_a(a).set_b(b). .... set_f(f);
Advantage: Named parameters. C++ does not have named parameters, the builder pattern is a way to emulate them.
In your case it could be implemented as follows:
#include<iostream>
struct myClass{
float a, b, c;
myClass(float a, float b, float c) : a(a),b(b),c(c)
{} //^^ use the initializer list
void print(){ // added for testing
std::cout << a << " " << b << " " << c << "\n";
}
};
struct myClassBuilder {
float a;
float b;
float c;
myClassBuilder& set_a(float x){ a = x; return *this; }
myClassBuilder& set_b(float x){ b = x; return *this; }
myClassBuilder& set_c(float x){ c = x; return *this; }
operator myClass(){
return myClass(a,b,c);
}
myClass build() {
return *this;
}
};
int main() {
auto m1 = myClassBuilder{}.set_a(1).set_b(2).set_c(3).build();
m1.print();
myClass m2 = myClassBuilder{}.set_a(1).set_b(2).set_c(3);
m2.print();
}
The operator myClass allows to convert the builder to the actual object (by calling the constructor). The build method is needed when you want to use auto. Live Demo. Of course you should use meaningful names, a,b,c.. is just as good as using an array and index.
B) Fix the design
Consider the single responsibility principle. If your class does too much at once then you have more severe problems than getting the parameters into the constructor in a "nice" way. For example, it is impossible to get acceptable test coverage for something that takes 20+ inputs.
Suppose 3 of the 20+ parameters are numDays, numMonth and numYears. Then you should group them together:
struct date_counter {
int numDays;
int numMonth;
int numYears;
};
If on the other hand, the numbers are really just a bunch of numbers, then use a container.
I think your class has a lot of responsibilities. The SOLID's principles, more specifically, Single responsability's principle specify that one class should do only one thing and like you need a constructor which takes 20 arguments, i guess your class is an all-in-one.
I'm not an advanced programmer. How can I overload the [] operator for a class that has two (or more) array/vector type variables?
class X
{
protected:
std::vector<double> m_x, m_y;
public:
double& operator[](const short &i) { return ???; }
};
What should I use for ???, or how can I do it (maybe adding other definitions?) to be able to call either variable?
Additional question: will this allow other classes of type class derived : public X access m_x and m_y for writing?
UPDATE:
Thank you everyone who answered, but I'm afraid that if I draw the line then the answer to my first question is no, and to the second yes. The longer version implies either an extra struct, or class, or plain setters/getters, which I wanted to avoid by using a simple function for all.
As it stands, the current solution is a (temporary) reference to each variable, in each class to avoid the extra X:: typing (and keep code clear), since m_x would have existed, one way or another.
you can write just a function for this, like:
double &get(unsigned int whichVector, unsigned int index)
{
return (whichVector == 0 ? m_x[index] : m_y[index]);
}
or use operator():
struct A
{
std::vector<int> a1;
std::vector<int> a2;
int operator()(int vec, int index)
{
return (vec == 0 ? a1[index] : a2[index]);
}
};
A a;
auto var = a(0, 1);
but still, this is kinda strange :) probably you should just give a const ref outside, like:
const std::vector<double> &getX() const { return m_x; }
and second question: protected will be convert into private in public inheritance (child/derived will have access to these memebers)
Assuming you want m_x and m_y indexed against the same parameter and a single return value:
struct XGetter
{
double& x;
double& y;
};
XGetter operator[](const short &i) { return { m_x[i], m_y[i] }; }
And the const overload:
struct XGetterReadOnly
{
double x;
double y;
};
XGetterReadOnly operator[](const short &i) const { return { m_x[i], m_y[i] }; }
The compiler will make a good job of optimizing away the intermediate classes XGetter and XGetterReadOnly where appropriate which maybe hard to get your head round if you're a new to C++.
If using mixin doesn't make you uncomfortable you could use tag dispatching like:
#include <utility>
#include <vector>
#include <iostream>
template <size_t I>
struct IndexedVector {
std::vector<double> v;
IndexedVector():v(10){}
};
template <size_t I>
struct tag {
int i;
};
template <size_t S, class = std::make_index_sequence<S>>
struct MixinVector;
template <size_t S, size_t... Is>
struct MixinVector<S, std::index_sequence<Is...>>: IndexedVector<Is>... {
template <size_t I>
double &operator[](tag<I> i) {
return IndexedVector<I>::v[i.i];
}
};
int main() {
MixinVector<2> mv;
mv[tag<0>{0}] = 1.0;
std::cout << mv[tag<0>{0}] << std::endl;
}
To use std::index_sequence you need however compiler supporting c++14 (you could though implement it yourself in c++11). The approach is easily expandable to any number of vectors by simple MixinVector template parameter modification.
There are many broken things, either at conceptual and design level.
Are you able to point your finger simultaneously against two distinct things? No? That's why you cannot use one index to address two distinct vector retaining their distinction.
You can do many things: whatever way to "combine" two value int one is good
by a syntactic point of view:
return m_x[i]+m_y[x] or return sin(m_x[i])*cos(m_y[i]) or return whatever_complicated_expression_you_like_much
But what's the meaning of that? The point is WHY THERE ARE TWO VECTOR IN YOUR CLASS? What do you want them to represent? What do you mean (semantically) indexing them both?
Something I can do to keep their distinction is
auto operator[](int i) const
{ return std::make_pair(m_x[i],m_y[i]); }
so that you get a std::pair<double,double> whose fist and second members are m_x[i] and m_y[i] respectively.
Or ... you can return std::vector<double>{m_x[i],m_y[i]};
About your other question: Yes, inheriting as public makes the new class able to access the protected parts: that's what protected is for.
And yes, you cam R/W: public,protected and private are about visibility, not readability and writeability. That's what const is about.
But again: what does your class represent? without such information we cannot establish what make sense and what not.
Ok, stated your comment:
you need two different funcntions: one for read (double operator[](unsigned) const) and one for write (double& operator[](unsigned) const)
If you know vectors have a known length -say 200-, that you can code an idex transforamtion like i/1000 to identify the vector and i%1000 to get the index,so that 0..199 addres the first, 1000..1199 address the second 2000..2199 address the third... etc.
Or ... you can use an std::pair<unsigned,unsigend> as the index (like operator[](const std::pair<unsigned,unsigned>& i), using i.first to identify the vector, and i.second to index into it, and then call x[{1,10}], x[{3,30}] etc.
Or ... you can chain vetor together as
if(i<m_x.size()) return m_x[i]; i-=m_x:size();
if(i<m_y.size()) return m_y[i]; i-=m_y:size();
if(i<m_z.size()) return m_z[i]; i-=m_z:size();
...
so that you index them contiguously.
But you can get more algorithmic solution using an array of vectors instead of distinct vector variables
if you have std::array<std::vector<double>,N> m; instead of m_x, m_y and m_z the above code can be...
for(auto& v: m)
{
if(i<v.size()) return v[i];
i-=v.size();
}
You can return a struct has two double
struct A{
double& x;
double& y;
A(A& r) : x(r.x), y(r.y){}
A(double& x, double& y) : x(x), y(y){}
};
class X
{
protected:
std::vector<double> m_x, m_y;
public:
A operator[](const short &i) {
A result(m_x[i], m_y[i]);
return result;
}
};
Thank for editing to #marcinj
Hi Stack Exchange Experts,
I'm trying to collect pointers to different statistical distributions provided by Boost in one vector.
If distributions would be derived from one (virtual) parent class I could write something like
std::vector<Parent> v;
boost::math::normal_distribution<double> n;
boost::math::students_t_distribution<float> t(4);
boost::math::normal_distribution<double> *p1 = new boost::math::normal_distribution<double>(n);
boost::math::students_t_distribution<float> *p2 = new boost::math::students_t_distribution<float>(t);
v.push_back(p1);
v.push_back(p2);
and then iterate over the vector and apply functions etc. to the dereferenced pointers.
But since this is not the case I don't really know how to store the pointers in one place?
So my question is, if there is a way to store pointers to different template classes in one variable/list/vector... (that can be handled conveniently like std::vector for example).
Remark that for example the Boost pdf density function can be applied to the dereferenced pointers regardless of the specific type (so storing them in one vector makes sense in some cases).
//////////////////////////////////////////////////////////////////////////
I played around with the different (nice) answers and finally decided to stick to boost::variant in conjunction with boost::static_visitor.
Below is a full application that does what I outlined in my original question:
#include <boost/math/distributions.hpp>
#include <boost/variant.hpp>
#include <vector>
#include <iostream>
//template based visitor to invoke the cdf function on the distribution
class cdf_visitor_generic : public boost::static_visitor<double>
{
public:
//constructor to handle input arguments
cdf_visitor_generic(const double &x) : _x(x) {}
template <typename T>
double operator()(T &operand) const {
return(boost::math::cdf(operand,_x));
}
private:
double _x;
};
//shorten typing
typedef boost::variant< boost::math::normal_distribution<double>, boost::math::students_t_distribution<double> > Distribution;
int main (int, char*[])
{
//example distributions
boost::math::normal_distribution<double> s;
boost::math::students_t_distribution<double> t(1);
//build a variant
Distribution v = t;
//example value for evaluation
double x = 1.96;
//evaluation at one point
double y = boost::apply_visitor( cdf_visitor_generic(x),v);
std::cout << y << std::endl;
//build a vector and apply to all elements of it:
std::vector<Distribution> vec_v;
vec_v.push_back(s);
vec_v.push_back(t);
for (std::vector<Distribution>::const_iterator iter = vec_v.begin(); iter != vec_v.end(); ++iter){
//apply cdf to dereferenced iterator
double test = boost::apply_visitor( cdf_visitor_generic(x), *iter);
std::cout << test << std::endl;
}
return 0;
}
The only drawback I see is that the type of distribution needs to be explicitly specified (in the variant) so it could be that boost::any adds more freedom.
Thank you for the great help!
Hank
You can use a variant:
std::vector<boost::variant<
boost::math::normal_distribution<double>,
boost::math::students_t_distribution<float>
> > v;
boost::math::normal_distribution<double> n;
boost::math::students_t_distribution<float> t(4);
v.push_back(n);
v.push_back(t);
I have several answers that show how to use these elements "polymorphically" (though the polymorphism is by statically compile typeswitching, instead of vtable dispatch). I'll add a link or two soon.
Generating an interface without virtual functions?
Avoid RTTI when dealing with pairs of objects
More involved: boost::mpl::fold for double parameter abstraction
Some of the linked answers show the "manual" approach to type erasure
PS. I should probably mention boost::any too, but I dislike it for several reasons. I shan't recommend it for this purpose.
You can't store pointers to unrelated types in single vector. One way to achieve this would be to make a vector of void*:
std::vector<void*>
But I would strongly discourage you from doing this as this is not much of a c++ way.
Better solution would be to create custom class hierarchy for storing different kinds of pointers, for example:
class DistributionBase {
public:
virtual ~DistributionBase() {}
}
template<typename T>
class Distribution : public DistributionBase {
public:
typedef T DistributionType;
T* distribution;
Distribution(T* d) : distribution(d) {}
~Distribution() { delete distribution; }
}
template<typename T>
Distribution<T>* make_distribution(T* d) {
return new Distribution<T>(d);
}
And then you can use it as follows:
std::vector<DistributionBase*> distributions;
distributions.push_back(make_distribution(new boost::math::normal_distribution<double>(n)))
distributions.push_back(make_distribution(new boost::math::students_t_distribution<float>(n)))
The problem is, that you have to store the type of distribution somewhere so you can static_cast to correct type:
boost::math::normal_distribution<double>* d = static_cast< Distribution<boost::math::normal_distribution<double> > >(distributions[0])->distribution;
This is just a snippet that should show you the point not a complete example.
You can wrap pointers around your common base class. Here I will use Template Method Pattern:
class Distribution {
public:
double pdf( double d) { doPdf( d)};
private:
virtual double doPdf( double d) {} = 0;
virtual ~Distribution() {}
};
class NormalDistribution : public Distribution {
private:
boost::math::normal_distribution<double> nd;
double doPdf( double d) { return pdf( nd, d);}
};
class StudentsTDistribution : public Distribution {
private:
boost::math::students_t_distribution<double> std;
double doPdf( double d) { return pdf( std, d);}
};
usage:
std::vector< boost::shared_ptr<Distribution> > v;
v.push_back( boost::make_shared<NormalDistribution>());
v.push_back( boost::make_shared<StudentsTDistribution>());
v[0]->pdf( 0.5); // draw from Gauss's distribution
v[1]->pdf( 0.5); // draw from fatter tails - t Student distribution
I am implementing a tridiagonal matrix and I have to be as efficient as possible. Obviously I will only hold the elements that contain data. I overloaded the operator() to act as an indexer into the matrix, but I want this operator to return a reference so that the user can modify the matrix. However, I cannot just return 0; for the non-tridiagonal elements since the zero is not a reference. How do I let the user modify the data on the tridiagonal, but when the operator() is used to inspect a non-tridiagonal element, only return 0 instead of a reference to 0?
below is the related class definition
template <class T>
class tridiagonal
{
public:
tridiagonal();
~tridiagonal();
T& operator()(int i, int j);
const T& operator()(int i, int j) const;
private:
//holds data of just the diagonals
T * m_upper;
T * m_main;
T * m_lower;
};
One trick you can use is to have the non-const operator() (int, int) method return a little helper object. The helper is used to differentiate between assigning into the matrix and just pulling out a value. This lets you have different behavior for the two operations. In particular, you can throw if someone tries to assign into a value that must be zero.
This code at least compiles for me in VC10, but obviously doesn't link.
template <class T>
class tridiagonal
{
public:
// Helper class that let's us tell when the user is
// assigning into the matrix and when they are just
// getting values.
class helper
{
tridiagonal<T> &m_parent;
int m_i, m_j;
public:
helper(tridiagonal<T> &parent, int i, int j)
: m_parent(parent), m_i(i), m_j(j)
{}
// Converts the helper class to the underlying
// matrix value. This doesn't allow assignment.
operator const T & () const {
// Just call the const operator()
const tridiagonal<T> &constParent = m_parent;
return constParent(m_i, m_j);
}
// Assign a value into the matrix.
// This is only called for assignment.
const T & operator= (const T &newVal) {
// If we are pointing off the diagonal, throw
if (abs(m_i - m_j) > 1) {
throw std::exception("Tried to assign to a const matrix element");
}
return m_parent.assign(m_i, m_j, newVal);
}
};
tridiagonal();
~tridiagonal();
helper operator()(int i, int j)
{
return helper(*this, i,j);
}
const T& operator()(int i, int j) const;
private:
T& assign(int i, int j, const T &newVal);
//holds data of just the diagonals
T * m_upper;
T * m_main;
T * m_lower;
};
int main(int argc, const char * argv[])
{
tridiagonal<double> mat;
std::cout << mat(0,0) << std::endl;
const tridiagonal<double> & constMat = mat;
std::cout << mat(2,3) << std::endl;
// Compiles and works
mat(2,3) = 10.0;
// Compiles, but throws at runtime
mat(1, 5) = 20.0;
// Doesn't compile
// constMat(3,3) = 12.0;
return 0;
}
It's been a while since I've done this, so you may find that you need to add a bit more to the helper class, depending on how you use the matrix.
Actually working through this is a good C++ exercise. :)
The issue you have here is an inappropriate interface. If your definition of a matrix is a 2D array of numbers such that every element of the matrix can be individually set, then a sparse, tridiagional matrix is paradoxically not a matrix (just as a square is not a modifiable rectangle - a classic example of inappropriate inheritance that doesn't obey the Liskov Substitution Principle).
In short, you'd be better off changing your interface to suit sparse, tridiagonal matrices rather than trying to hack it to work with the interface you've got. That said, if you must do it this way, then you are probably better off doing two things:
Modifying your const accessor to return T instead of const T& (I'm assuming we're only dealing with matrices of numbers here). Then you can just return 0 for the elements off the diagonal.
Modifying your non-const accessor to return a reference to a dummy element for locations off the diagonal, and crossing your fingers :) Alternatively, you could change the specification to throw in such cases, but that might be a little unfriendly.
One other alternative (short of reworking the interface properly) might be to return proxy objects instead of Ts. The proxy for dummy elements would then throw when you try and set the value using it.
Returning by reference requires that you return a valid object of the specified type. The simplest way to accomplish what you want is to keep a static T object that represents 0, and return it instead.
Alternatively, you could return a pointer.
Just add an extra member representing some dummy value and make sure it always reads as 0.
template<typename T>
class tridiagonal
{
// usual stuff...
T& operator() (int j, int j)
{
// if not explicitly stored, reset to default before returning.
return stored(i,j)? fetch(i,j) : (m_dummy=T());
}
private:
// dummy element used to "reference" elements outside the 3 diagonals.
T m_dummy;
// check if (i,j) is on 3 diagonals.
bool stored (int i, int j) const;
// access element on 3 diagonals. precondition: stored(i,j)==true.
T& fetch (int i, int j);
//holds data of just the diagonals
T * m_upper;
T * m_main;
T * m_lower;
};
Note that technically speaking, someone could trick you as such:
tridiagonal<int> m(4,4);
T * dummy = &m(3,0); // *dummy == 0.
*dummy = 1; // *dummy == 1.
std::cout << *dummy; // prints 1.
But that's not necessarily a problem.
I have a function to compute gradient of different variable defined on set of neighbor points. The algorithm is always the same, but depending on what is computed, different member data of the neighbors are accessed, e.g. when computing gradient of velocity, use Node::velocity, when computing gradient of stress, use Node::stress. What is the best way to avoid writing the same function several times?
I had several possibilities in mind:
Pass lambda function (c++0x)
or callable object returning that particular member data in question, called like
gradVelocity=computeGradient(listOfNeighbors,[](const Node& n){ return n.velocity; });
The minus is extra function call at every read.
Template the function based on integer saying what is being computed:
enum{VAL_VELOCITY=0,VAL_STRESS,VAL_SOMETHING};
template<int what> computeGradient(const std::list<Node>& neighbors){
/*loop over neighbors*/
value=(what==VAL_VELOCITY?neighbor.velocity:((what==VAL_STRESS)?neighbor.stress:neighbor.something);
/* and so on */
}
/* called like this */
gradVelocity=computeGradient<VAL_VELOCITY>(neighbors);
It should be perhaps efficient (hoping compiler will optimize the conditional with constants away in individual instantiations), but readability and maintainability is pretty low.
Some better idea?
If all of your fields have the same types, it's easy to use pointers to members:
struct Node
{
double stress;
double velosity;
};
void foo(Node* pNode, double Node::*pValue)
{
cout << pNode->*pValue << endl;
}
int main()
{
Node n1 = { 1, 2 };
foo(&n1, &Node::stress);
foo(&n1, &Node::velosity);
}
Update: If not, it's still easy to combine pointers to members with templates:
struct Node
{
double stress;
double velosity;
int dimension;
};
template<class T>
void foo(Node* pNode, T Node::*pValue)
{
cout << pNode->*pValue << endl;
}
int main()
{
Node n1 = { 1, 2 };
foo(&n1, &Node::stress);
foo(&n1, &Node::velosity);
foo(&n1, &Node::dimension);
}
I think this is probably the most efficient possible way. It's pretty vivid too.
Pointer to member is what you need. The type is written as T S::* T is the type of the data member, S is your struct or class. Here is a small example:
#include <iostream>
struct Foo
{
int a;
double b;
Foo(int a, double b)
: a(a), b(b)
{ }
};
template<typename T, T Foo::* mem>
void print(const Foo& foo)
{
std::cout << foo.*mem << std::endl;
}
int main()
{
Foo f(5, 3.14);
print<int, &Foo::a>(f);
print<double, &Foo::b>(f);
}
I am a huge fan of Boost.Fusion, and more specifically, the Boost.Fusion.Map, which let you build a type -> value kind of map.
struct Velocity {};
struct Stress {};
typedef boost::fusion::map<
std::pair<Velocity, double>,
std::pair<Stress, int>
> Map;
Map map;
Now, you can access the map with types:
boost::fusion::at_key<Velocity>(map)
returns a reference to a variable of type boost::fusion::result_of::at_key<Velocity, Map>::type
With appropriate wrapping, you get:
extern Velocity const velocity;
extern Stress const stress;
myItem.access(stress) = 3;
And of course, since we are talking templates, no runtime penalty, at all :)
What about inheriting from Node and using virtual access? It would even be possible to use CRTP to avoid the virtual call.
You can combine velocity, stress, something in a single array and access them based on enum index.
struct Node
{
int attributes[3]; // contains 'velocity', 'stress', 'something';
enum { VAL_VELOCITY=0, VAL_STRESS, VAL_SOMETHING };
};
Usage:
Node n;
n.attributes[Node::VAL_VELOCITY] = <value>; // writing 'Node::velocity'
<otherthing> = n.attributes[Node::VAL_SOMETHING]; // reading 'Node::something'
[Note: If you want to keep attributes inside private region then provide getter and setter methods in Node for accessing them.]