I have the following class, here is it full prototype:
class FlowEdge{
private:
const uint32_t from_;
const uint32_t to_;
const double capacity_;
double flow_;
public:
FlowEdge();
FlowEdge(uint32_t from, uint32_t to, double capacity);
uint32_t from() const;
uint32_t to() const;
uint32_t other(uint32_t vertex) const throw(std::invalid_argument);
double getCapacity() const;
double getFlow() const;
double residualCapacityTo(uint32_t vertex) const throw(std::invalid_argument);
void addResidualFlowTo(uint32_t vertex, double delta) throw(std::invalid_argument);
};
I use this class as std::deque element type: std::deque<FlowEdge> in another class. When I compile my project I receive an error said that my FlowEdge class have no available operator= method. This method is created by compiler by default, isn't it? What could be a problem? I haven't operator= nor in public, nor in protected section.
The compiler generates an operator= for you if it is able to do so. It's not able in your case, because you have a const member in the class. Such a member cannot be assigned to, so the default copy assignment operator wouldn't be well-defined. If you want to assign objects of this class, you have to provide a custom one, implementing it to preserve the semantics you want of the const member.
Of course, the easier alternative would be to make capacity_ a non-const double. Generally, const data members are only useful in very specific situations, and they're usually more trouble than they're worth.
Related
Maybe it is a trivial question, but I can't actually find an answer. If I have a class like in the example below do I need to provide both const and non-const version of functions like in case of std::vector? Would a single constexpr function do the same job?
template <typename Type>
class Collection
{
public:
virtual ~Collection() {}
virtual size_t size() noexcept = 0;
virtual size_t size() const noexcept = 0;
virtual Type operator[](size_t index) noexcept = 0;
virtual Type operator[](size_t index) const noexcept = 0;
};
It depends. If the non-const version would do the same thing as the const version, then no. If someone has a non-const instance of a class, they can still call const methods.
There are some methods that may need both. Consider your indexing operator. If it instead returned a reference to the type, you would probably want both:
virtual Type& operator[](size_t index) noexcept = 0;
virtual const Type& operator[](size_t index) const noexcept = 0;
The methods aren't exactly the same because they are returning different types. This would mean that if someone has a const instance of your type, they could not get a mutable reference to an element.
A single constexpr function could do the job as long as the potential const/non-const implementations would be the same.
So I defined a class on C++ that inherits from a vector of pointers:
class SuperBinList : public std::vector<SuperBin*>{
public:
SuperBinList();
SuperBinList(const std::vector<SuperBin*>& superBinList);
virtual ~SuperBinList();
SuperBinList& operator += (SuperBin* superBin);
SuperBinList& operator += (const SuperBinList& superBin);
void sortByZbi(const double sys);
void sortBySoverB() const;
};
The SuperBin class itself is defined as:
class SuperBin{
public:
SuperBin(const VI index, const double nSig, const double nBkg, const VS mPerpLabel, const VS rIsrLabel, const VS visLabel);
virtual ~SuperBin();
VI getIndex();
double getNsig();
double getNbkg();
double getSoverB();
double getBinZbi(const double sys);
VS getMperpLabel();
VS getRisrLabel();
VS getVisLabel();
SuperBin* tryMerge(SuperBin* superBin, double sys);
private:
VI index_;
double nSig_;
double nBkg_;
double sOverB_;
VS mPerpLabel_;
VS rIsrLabel_;
VS visLabel_;
};
Now the problem I'm having is that I want the SuperBinList class to be able to sort itself in descending order in terms of any of the (double type) members of the SuperBin class (such as sOverB). For this I tried the following method using a lambda function:
void SuperBinList::sortBySoverB() const{
std::sort(this->begin(), this->end(), [](const SuperBin* lhs, const SuperBin* rhs){
return lhs->getSoverB() < rhs->getSoverB();});
}
The top error I'm getting is:
error: passing 'const SuperBin' as 'this' argument discards qualifiers [-fpermissive]
return lhs->getSoverB() < rhs->getSoverB();});
Which, as I understood from similar threads, has to do with the const specifiers. However, I'm still not sure what it is that I am doing wrong. Any help would be greatly appreciated. Please pardon my ignorance as I am a physics PhD and not a computer scientist.
You have your SuperBinList::sortBySoverB() function defined as const, which means it is not allowed to modify SuperBinList, and
this will have the type const SuperBinList *, rather than SuperBinList *
Similarly, your lambda is define with const pointers const SuperBin* lhs, meaning you can only call const functions.
Change your function definitions to void SuperBinList::sortBySoverB() {} and double getSoverB() const {}, and it should compile. (Generally member functions should be marked const if they are read-only operations like getters).
I have a slight problem. I have a Matrix class defined as follows (in row-major form):
template<typename T>
class Matrix {
private:
class RowVector {
private:
T *_vec;
std::size_t _l;
public:
RowVector(T *vec, std::size_t l);
const T &operator[](std::size_t index) const;
T &operator[](std::size_t index);
operator std::vector<T>() const;
};
std::vector<T> _data;
std::size_t _m;
std::size_t _n;
public:
Matrix(std::size_t m, size_t n, const T &elem = T());
const RowVector operator[](std::size_t index) const;
RowVector operator[](std::size_t index);
std::size_t getm() const;
std::size_t getn() const;
void fill(const T &elem);
void fillRow(std::size_t index, const T &elem);
void fillCol(std::size_t index, const T &elem);
Matrix &transpose(unsigned int i = 1);
const std::vector<T> &data() const;
};
and wish to overload two RowVector operators=
typename Matrix<T>::RowVector &operator=(const std::vector<T> &vec);
typename Matrix<T>::RowVector &operator=(const Matrix<T> &mat);
so I can return a RowVector & using A[0] and reassign its value using either a vector or a matrix. Keep in mind that I (presumably) can ignore the rule of three because I provide no explicit way for the client to construct a RowVector object.
However, in attempting to write the function bodies for the overloads, I have come across a problem: that
(1) I cannot copy-construct a vector/Matrix object that will persist outside of the operator='s scope so that I can assign its data() to _vec and its size() to _l.
(2) I cannot directly modify _data since it is not a static variable; even if I could, I have no way to discover the index so I can overwrite the relevant region of memory in the enclosing Matrix object.
Do you know of any way in which this can be done? These would be two very useful assets for my class.
I would like to be able to write something like this:
Matrix<int> A(3, 4);
std::vector<int> v {1, 2, 3, 4};
Matrix<int> row(1, 4, 3);
// *****************
A[0] = v;
A[1] = row;
// *****************
(Hopefully my variable names are self-explanatory)
I think my prototypes are correct, but I just can't find a way to do this.
Thanks!
T *_vec;
std::size_t _l;
This is a problematic design! I don't say it is incorrect per se, but you then need to correctly manage the memory yourself. Ignoring the rule of three (five) is a very dangerous in this respect. You have a pointer to (potentially?) dynamically allocated memory, so there must be some instance that is responsible for its deletion (must not necessarily be your RowVector, but what else then?).
From pure technical aspect, you even can let _vec point to some vector's data, provided you gurantee that this other vector lives as long as you want to access the data via pointer – which in general requires, though, quite some effort.
Safest would be having each row maintain its own data, copying (or moving) it from the other vector. Then easiest is storing the data in a std::vector of its own (replacing the raw pointer).
If you want to avoid copying data around and instead share data between different matrices and their rows, then you could maintain the data via a std::shared_ptr - either maintaining a raw array or possibly even a heap-allocated std::vector.
If you opt for either std::vector or std::shared_ptr, then copy and move constructors and assignment operators get totally simple:
class C
{
public:
C(C const&) = default;
C(C&&) = default;
C& operator= (C const&) = default;
C& operator= (C&&) = default;
};
All of these defaults will do copying/moving as per member, and both std::vector and std::shared_ptr have the appropriate constructors and operators available already, so you'd be fine – and you now can violate the rule of five, dropping the destructor, as the default one (calling all the member's destructors) suffices.
If you consider shared pointers: be aware that you then cannot assign a std::vector's data to: std::vector does its own memory management, and you will end up in double deletion of, so in this specific case, you'd still have to create a copy of. You might possibly end up in multiple constructors and assignment operators:
std::shared_ptr<std::vector<int>> _data;
// assign shared pointers
RowVector(RowVector const&) = default;
RowVector(RowVector&&) = default;
// need to create copies of: we never know about the scope of the vector passed!
RowVector(std::vector<int> const& data) : _data(new std::vector<int>(data)) { }
RowVector(std::vector<int>&& data) : _data(new std::vector<int>(std::move(data))) { }
// we *are* sharing already -> no need to copy:
RowVector(std::shared_ptr<std::vector<int>& data) : _data(data) { }
Assignment operators analogously.
Side-note: If you want to have a mathmatical nxm matrix, pretty sure you don't want to have a jagged array. I'd assume your Matrix class' constructor already creates an appropriate vector of vectors, then for assignment, you'd have yet to check length:
// defaults not suitable any more!
RowVector& RowVector::operator=(RowVector const& other)
{
// still assuming shared pointer:
// (for vector, replace -> with .)
if(other._data->size() != _data.size())
{
throw SomeException();
}
_data = other._data;
}
RowVector(RowVector&& other)
{
if(other._data->size() != _data.size())
{
throw SomeException();
}
_data = std::move(other._data);
}
I have a c++ class that has a private array member.
class array_test
{
public:
std::tuple<double*, int> get_vector_member();
private:
double test_array[3];
};
In C++11 is there a better method call to get a double[] that doesn't involve grabbing double as a pointer. I am worried that either myself or someone else will delete the pointer and cause some strange undefined behavior.
I hope the fact I didn't include an implementation for get_vector_member is an issue.
How about providing typical C++ field accessor functions, with a const and non-const overload, returning a reference to the field?
class X
{
double data[3];
public:
// Accessors
double (&get())[3] { return data; }
const double (&get() const)[3] { return data; }
};
In C++14 this code is a bit easier to write:
auto & get() { return data; }
const auto & get() const { return data; }
You could make it an std::array. Some reasons why they're superior to raw arrays:
Easy element access with the front and back member functions.
They're copy constructible and assignable.
Optional bounds-checked access.
Cool comparison operations like ==, != and <.
The fill member function.
No weird syntax when passing by reference.
Then return that by reference:
class array_test
{
public:
const std::array<double, 3>& get_array_member() const;
private:
std::array<double, 3> test_array;
};
I've found some good examples of functors on SO like this one, and all the convincing examples seem to use state in the class that defines operator().
I came across an example in a book that defines the function call operator without having state, and I can't help but feel like this is an awkward usage, and that a normal style function pointer, would be better than using operator() in every way here - less code, less variables (you have to instantiate the comparators), its probably more efficient due to the instantiation, and no loss of meaning or encapsulation (since it's just one function).
I know std::sort lets you pick between operator() classes and functions, but I've always just used the functions because of the above logic.
What are the reasons why a class might be preferred?
Here's the example (paraphrased):
class Point2D {
//.. accessors, constructors
int x,y;
};
class HorizComp {
public:
bool operator()(const Point2D& p, const Point2D& q) const
{ return p.getX() < q.getX(); }
};
class VertComp {
public:
bool operator()(const Point2D& p, const Point2D& q) const
{ return p.getY() < q.getY(); }
};
template <typename E, typename C>
void printSmaller(const E& p, const E& q, const C& isLess) {
cout << (isLess(p, q) ? p : q) << endl; // print the smaller of p and q
}
//...
// usage in some function:
Point2D p(1.2, 3.2), q(1.5, 9.2);
HorizComp horizComp;
VertComp vorizComp;
printSmaller(p, q, horizComp);
printSmaller(p, q, vorizComp);
The typical reason is that when you do this:
bool less_than(const Point&, const Point&);
// ...
std::sort(..., &less_than);
The template argument for the predicate is the following:
bool(const Point&,const Point&)
Since the sort function receives a function pointer, it is more difficult for the compiler to inline the predicate use inside std::sort(). This happens because you could have another function
bool greater_than(const Point&, const Point&);
which has the exact same type, meaning the std::sort() instatiation would be shared between the two predicates. (remember that I said that it makes inlining more difficult, not impossible).
In contrast, when you do this:
struct less_than {
bool operator()(const Point&, const Point&) const;
};
// ...
std::sort(..., less_than());
struct greater_than {
bool operator()(const Point&, const Point&) const;
};
// ...
std::sort(..., greater_than());
The compiler generates a unique template instantiation for std::sort() for each predicate, making it easier to inline the predicate's definition.
One reason is run-time efficiency. If you pass a pointer to a function, the compiler has to be unusually clever to produce code for that function inline. Passing an object that defines operator() makes it much easier for the compiler to produce the code inline. Especially for something like sorting, this can increase speed quite substantially.
In C++11, another reason to use a class is for convenience -- you can use a lambda expression to define the class.
Others have made good points about the ability for the compiler to inline the functor. One other possibile advantage of functor objects vs. function pointers is flexibility. The functor might be a template, maybe a derived class, perhaps it has run time configuration (even if stateless at the time operator() is called etc.
Another reason is that sometimes one comparison function is not enough. Let's say we have a vector of pointers:
struct X { string name; };
vector<shared_ptr<X>> v;
Now if we want to sort the vector by name, we have to define our own predicate for the sort function:
struct Cmp1
{
bool operator()(const shared_ptr<X>& left, const shared_ptr<X>& right) const
{ return left->name < right->name; }
};
That's cool, but what do we do when we need to find the objects with specific name? To work with equal_range, the predicate needs to have two different comparison functions:
struct Cmp2
{
bool operator()(const shared_ptr<X>& left, const string& right) const
{ return left->name < right; }
bool operator()(const string& left, const shared_ptr<X>& right) const
{ return left < right->name; }
};
This allows us to call equal_range with a string name object:
equal_range(v.begin(), v.end(), name, Cmp2())
In template libraries where the state of functor argument is not known at definition time, argument of class type provides a more generic interface than none-instance function pointers.
STL is a great example where the statefull or stateless perdicates and functors can be used as parameters to classes and functions.
If template programming is not part of the plan, function pointer is superior to stateless functor class; a single instance of function can accept all function pointers of a specific signature and code size is minimized. But in case there is a minimal probability of future library extension, functor makes it more generic.