Consider the following code:
class B
{
int x;
public:
B() : x( 10 ) {}
int get_x() const { return x; }
void set_x( int value ) { x = value; }
};
class A
{
boost::shared_ptr<B> b_;
public:
boost::shared_ptr<B> get_b() const { return b_; } // (1)
};
void f( const A& a)
{
boost::shared_ptr<B> b = a.get_b();
int x = b->get_x();
b->set_x( ++x ); // (2)
}
int main()
{
A a;
f( a );
return 0;
}
In this code (2) compiles without any errors or warnings independently the fact that get_b is a const function and a is a const object.
My question is how do you deal with this situation? The best I could use is to change (1) to the following:
boost::shared_ptr<const B> get_b() const { return b_; } // (1)
But I should always remember that I should add const to the return type. That's not very convenient. Is there a better way?
This doesn't actually have anything to do with shared pointers per se. I mean if you had a plain pointer you'd have exactly the same problem and would solve it in exactly the same way, that is
const B* get_b() const {return b_; }
If you left it like
B* get_b() const {return b_; }
you'd have the same problem.
Well, you have found the solution yourself.
boost::shared_ptr<const B> get_b() const { return b_; } // (1)
It's the only const-correct way to do it.
Related
You can redefine operator << in class by overload it.
However, how do you code it so that it would operates specific to a certain class member?
for example
class C
{
int a;
double b;
}
// I would like something like
void main ()
{
C c;
c.a << 1; // sets class member a to value 1;
}
I want a operator defined in Class C that operates specifically to class member a.
a pesudo-code would be
class C
{
int a;
double b;
void operator << (istream & fin)
{
... fin.get()... some code
}
}
Stating the obvious for a moment, assuming the variable is public, you'd use:
class C
{
int a;
double b;
}
// I would like something like
void main ()
{
C c;
c.a = 1; // sets class member a to value 1;
}
The << and >> operators are bit shifts, which have their own meaning. Overloading those for your own purpose is probably a bad idea.
The C++ way of doing things is to avoid setting member variables externally where possible (e.g. using RAII approaches, to set data at initialisation)....
class C
{
public:
C(int a, double b) : a(a), b(b) {}
int getA() const { return a; }
double getB() const { return b; }
private:
int a;
double b;
};
.... Or by adding a setter method if you really need it, e.g.
class C
{
public:
C(int a, double b) : a(a), b(b) {}
int getA() const { return a; }
double getB() const { return b; }
void setA(int v) { a = v; }
void setB(double v) { b = v; }
private:
int a;
double b;
};
You could in theory generate a new type, and overload the operators for that type, but it's not something I'd recommend (because changing the meaning of an operator is almost always a bad idea)
struct MyIntType {
int i;
// overload cast operator
operator int () {
return i;
}
// assign
MyIntType& operator = (const int& v) {
i = v;
return *this;
}
// not recommended :(
MyIntType& operator << (const int& v) {
i = v;
return *this;
}
};
class C
{
public:
MyIntType a;
double b;
};
void main ()
{
C c;
c.a << 1;
}
Having read your comment above, it sounds like you want to do this:
class C
{
public:
// I'm still not recommending this :(
C& operator << (const int& v) {
a = v;
return *this;
}
private:
int a;
double b;
};
void main ()
{
C c;
c << 1; //< now sets c.a
}
The code below is a simplified version of the actual problem I am facing.
Assume I do not have permission to modify class A (as it is external library), and its already widely used in my existing code base.
The const & assignment from a temporary object (direct constructor) which also return a const & member variable via implicit conversion is not valid in this case.
How do I prevent or make it legal in this case so that the caller gets the correct A value?
class A
{
public:
A() { }
A(int _r, int _g, int _b)
: r(_r), g(_g), b(_b)
{
}
~A(){ }
int GetR() const { return r; }
int GetG() const { return g; }
int GetB() const { return b; }
private:
int r = 0;
int g = 0;
int b = 0;
};
class Foo
{
public:
Foo() : Foo(A()) {}
Foo(int _r, int _g, int _b) : a(A(_r, _g, _b)) {}
explicit Foo(const A& _a) : a(_a) {}
Foo& operator=(const A& a)
{
*this = Foo(a);
return *this;
}
operator A() const { return a; }
operator const A&() const { return a; }
private:
A a;
};
int main()
{
const A& a = Foo(200, 100, 300);
std::cout << a.GetR() << a.GetG() << a.GetB() << endl; // I may not get 200 100 300 here as Foo is already out of scope
return 0;
}
Motivation
Some background on why I am implementing a class as above. The actual purpose of class Foo is to contain 2 different objects, which actually has the same purpose, just different way of storing data internally. For example, let's say class A and class B, which stores RGB value of color in int and floating (normalized) respectively. And as mentioned above, I do not have permission to modify class A, and its already widely used in my code base.
There are tons of function in my code base which takes in const A& and const B& as a function param. So I am trying to unify this 2 classes for a particular case, where I can just pass in Foo in those places and it will work as expected.
You can apply ref-qualified member functions (since C++11), i.e. mark the conversion operator with lvalue-reference, to prevent it being called on temporaries (rvalues).
class Foo
{
public:
... ...
operator A() const { return a; }
operator const A&() const & { return a; }
operator const A&() && = delete;
... ...
};
Then
const A& a = Foo(200, 100, 300); // invalid; invokes deleted operator
const A& a = static_cast<A>(Foo(200, 100, 300)); // fine; invokes operator A()
I have some large amounts of strings grouped in some classes, all grouped in one final giant class. This class must be filled up by another class and its immutable content exposed to some clients. (Of course, these classes are more complex, this is a simplified schematic representation.)
Solution 1:
class A
{
friend class M;
private:
B m_b;
C m_c;
D m_d;
public:
const B& GetB() const { return m_b;}
const C& GetC() const { return m_C;}
const D& GetD() const { return m_D;}
private:
B& GetB() { return m_b;}
C& GetC() { return m_C;}
D& GetD() { return m_D;}
}
where B is something like:
class B
{
friend class M;
private:
std::string m_camel;
std::string m_pink;
std::string m_vandergraaf;
public:
const std::string& Camel() const { return m_camel;}
const std::string& PinkFloyd() const { return m_pink;}
const std::string& VanDerGraafGenerator() const { return m_vandergraaf;}
private:
void SetCamel(const char* prog) { m_camel = prog;}
void SetPinkFloyd(const char* prog) { m_pink = prog;}
void SetVanDerGraafGenerator(const char* prog) { m_vandergraaf = prog;}
}
A better solution, that avoids friend for protected is to expose the write access class to M and the base one, read-only to the world.
Solution 2:
class A
{
protected:
B m_b;
C m_c;
D m_d;
public:
const B& GetB() const { return m_b;}
const C& GetC() const { return m_C;}
const D& GetD() const { return m_D;}
}
// only visible to M
class A_Write: public A
{
public:
B& GetB() { return m_b;}
C& GetC() { return m_C;}
D& GetD() { return m_D;}
}
Same thing for B, maybe. Not a very good solution since the clients can also derive their own classes.
A better but more constraint variant is solution 3:
class A
{
private:
const B m_b;
const C m_c;
const D m_d;
public:
const B& GetB() const { return m_b;}
const C& GetC() const { return m_C;}
const D& GetD() const { return m_D;}
protected:
A(const B& b, const C& c, const D& d): m_b(), m_c(c), m_d(d) {}
}
// only visible to M
class A_Write: public A
{
public:
A_Write(const B& b, const C& c, const D& d): A(b, c, d) {}
}
My preferred solution is 4, which is ... 3 but with B,C,D as simple structs instead of classes. So M can do anything it wants directly in B, C, D, then construct a A_Write.
Any better ideas ?
A possible approach could be to use a proxy that reduces the interface of your class.
The class M will instantiate/receive an instance of S (so as to be able to modify it using its interface), but it will return a proxy P to the readers (that won't manage to modify it).
It follows a minimal example:
struct S {
void value(int v) noexcept { t = v; }
int value() const noexcept { return t; }
private:
int t{0};
};
struct P {
P(S& s): b{s} { }
int value() const noexcept { return b.value(); }
private:
S& b;
};
int main() {
// the class: full interface
S s;
// the proxy: reduced interface
P p{s};
}
I am trying to get multiple pointer in one get methods, without leaving the user the right to modify the data. Here is my implementation :
class A {
public:
bool getAB( int** a, int** b ) const
protected :
int * a_;
int * b_;
}
bool getAB( int** a, int** b ) const
{
*a = a_;
*b = b_;
return true;
}
But this way, user can modify, and even free the data.
I could implement like two different getter wich return const int*, but i would like to know if there is a correct way to do that.
In c++, the proper way to return multiple values is by reference:
class A {
public:
bool getAB( int*& a, int*& b ) const
{
a = _a;
b = _b;
}
protected :
int * a_;
int * b_;
}
(I also made the method inline to simplify the example)
If you want to disallow altering the data, return a pointer to const:
class A {
public:
bool getAB( const int*& a, const int*& b ) const
{
a = _a;
b = _b;
}
protected :
int * a_;
int * b_;
}
Note that the user can still call delete (but not free) on the result of getAB; see this question for more info. If you want to disallow delete, you can replace pointers by smart pointers (e.g. std::unique_ptr).
Actually, if you want your code to be compatible with c++ exceptions, you should never hold two pointers in your class (and rarely, if ever, hold one pointer).
You can indeed protect a little more the internal values, but it will be hard to forbid a delete. Here is the best I could do
class A {
public:
bool getAB( const int ** const a, const int ** const b ) const;
A(int * a, int *b): a_(a), b_(b) {}
protected :
int * a_;
int * b_;
};
bool A::getAB( const int ** const a, const int ** const b ) const
{
*a = a_;
*b = b_;
return true;
}
int main() {
int i=1;
int j=2;
A a(&i, &j);
const int * p1;
const int * p2;
// int * p2; error
a.getAB(&p1, &p2);
// *p1 = 3; error
// delete p1; unfortunately gives no errors
cout << *p1 << " " << *p2 << endl;
return 0;
}
It does require a pointer to const, but delete is unfortunately allowed. And it is not possible to pass a const pointer, because a const pointer has to be immediately initialized.
The title is a bit vague but I can't come up with a better wording, here's the deal:
class A
{
public:
A();
A( const PropertyB& b );
PropertyA GetPropertyA();
PropertyB GetPropertyB();
SetPropertyA( const PropertyA& b );
SetPropertyB( const PropertyB& b );
//assignment not allowed
};
Suppose I want to use an std::vector< A >, but, it only makes sense to have a vector of A if all it's elements have the same value for PropertyB. The current solutions is to supply a contrcutor-like method to create such array which guarantees all elements of the returned array have the same value for PropertyB, and a method that checks if that is the case:
Array MakeArray( size_t, const PropertyB& );
bool CheckIfArrayIsSane( const Array& );
So users can still call SetPropertyB() on the elements, but have a utility to check it and bail out if someone did:
Array x( MakeArray( 3, someValue ) );
x.SetPropertyA( aaa ); //should be allowed
x.SetPropertyB( someOtherValue ); //should NOT be allowed
//somewhat further in the program
if( !CheckIfArrayIsSane( x ) )
throw InsaneArrayExcpetion();
While this works, it's error-prone since it is hard to force this check everywhere and not forget it, and clutters the code with checks.
Approcahes that do not work:
Making SetPropertyB() private, and making MakeArray a friend function: then SetPropertyB() is not accessible anymore for users that simply want to use A without caring about the array.
Wrapping std::vector< A > in a seperate class and only returning const A& references: this would mean the other setters like SetPropertyA() can also not be called, but users should be able to call them. It's only SetPropertyB() that should be disallowed.
One more intrusive approach that would work but feels a bit unelegant, and needs extra functions to convert between the two etc:
class AWithFixedPropertyB
{
public:
A( const PropertyB& b );
PropertyA GetPropertyA();
PropertyB GetPropertyB();
SetPropertyA( const PropertyA& b );
};
class A : public AWithFixedPropertyB
{
public:
//contrcutors etc
SetPropertyB( const PropertyB& b );
};
//ok, users cannot modify property B in this Array
typedef std::vector< AWithFixedPropertyB > Array;
What would be the most elegant solution for this problem?
This doesn't make sense, from an OO design viewpoint. Remember the Liskov Susbsitution Principle: A is-a B whenever an A object can be used in the place of a B object? Per that rule, the elements of your proposed std::vector<A> fail the is-an-A test, since you can't set their B property. Yet std::vector<A> is supposed to be a container of A objects.
In C++ we have private inheritance, and this makes explicit that the derived class does not have an is-a relationship with its parent. You can use that as follows:
class A_fixed_B : private A
{
A_fixed_B(A const& src) : A(src) {}
A const& asA() const { return *this; } // Base Conversion is OK inside class.
using A::GetPropertyA;
using A::GetPropertyB;
using A::SetPropertyA;
};
You can now create a std::vector<A_fixed_B> which behaves as you'd probably expect.
The easier thing to do would be to wrap std::vector<A> and return some form of proxy object.
class WrappedVectorA : private std::vector<A> {
struct MyProxy {
MyProxy(A& ref) { ptr = &ref; }
A* ptr;
PropertyA GetPropertyA() const { return ptr->GetPropertyA(); }
PropertyB GetPropertyB() const { return ptr->GetPropertyB(); }
SetPropertyA( const PropertyA& b ) { return ptr->SetPropertyA(b); }
operator=(const A& a) { *ptr = a; }
operator const A&() const { return *ptr; }
operator A() { return *ptr; }
};
public:
MyProxy operator[](int index) {
return std::vector<A>::operator[](index);
}
const MyProxy operator[](int index) const {
return const_cast<A&>(std::vector<A>::operator[](index));
}
};
It's really kind of ugly, but it'll work. I guess you'd also need to wrap the iterators and at(). However, A itself doesn't need to know anything about this, and normal std::vector<A> are completely untouched.
I'll go with that :
class IA {
public:
virtual ~IA() {}
virtual PropertyA& GetPropertyA() = 0;
virtual void SetPropertyA(const PropertyA& a) = 0;
};
class A : public IA
{
public:
A();
A( const PropertyB& b );
PropertyA& GetPropertyA();
PropertyB GetPropertyB();
void SetPropertyA( const PropertyA& b );
void SetPropertyB( const PropertyB& b );
};
template< PropertyB value >
class fixedVector {
private:
std::vector<A> _tab;
public:
void pushback() {_tab.pushback(A(value)); }
IA& get(unsigned int i) { return _tab[i]; }
void popback() { _tab.pop_back(); }
};
If your A object are instanciate by a proxy, you could use a directly a std::vector< std::autoptr<AI> >;
Use a flyweight for the storage of PropertyB and throw an exception in SetPropertyB, if the count of elements in the flyweight is greater than 1 after the assignment.
Different PropertyBs will not be allowed no matter which container you store the As in.
#include <boost/flyweight.hpp>
class A
{
public:
A();
A( const PropertyB& b );
PropertyA GetPropertyA();
PropertyB GetPropertyB();
SetPropertyA( const PropertyA& b );
SetPropertyB( const PropertyB& b );
private:
PropertyA a;
boost::flyweights::flyweight<PropertyB> b;
};
A::SetPropertyB(const PropertyB& item)
{
b = item;
if(b.size() > 1) // you may have to implement flyweight::size() yourself
// should be able to do this based on core::factory().size();
throw InsaneArrayExcpetion();
}
Haven't actually tested if this code compiles, but it gives you the idea.
I would go with "Wrapping std::vector< A >..." approach. In that way user of the class will not be able to modify the objects in the vector where as if they want to call SetPropertyB they can create a copy of the object returned from this wrapper and use that method.
Use a policy base class to determine which fields can be set - this will generate a compile time error if you try to set the wrong property. The downside of course is that A is no longer simply A, but is typed on the policy.
Code:
#include <iostream>
#include <vector>
#include <boost/utility.hpp>
#include <boost/type_traits.hpp>
#include <boost/static_assert.hpp>
class AllPolicy
{
public:
void setA(int a) { _setA(a); }
void setB(int b) { _setB(b); }
private:
virtual void _setA(int a) = 0;
virtual void _setB(int b) = 0;
};
class APolicy
{
public:
void setA(int a) { _setA(a); }
typedef void setB;
private:
virtual void _setA(int a) = 0;
};
class BPolicy
{
public:
void setB(int b) { _setB(b); }
typedef void setA;
private:
virtual void _setB(int b) = 0;
};
template <typename Policy>
class A : public Policy
{
public:
A(int a = 0, int b = 0) : _a(a), _b(b)
{
}
A(A const& v) : _a(v._a), _b(v._b)
{
}
~A() {}
A& operator=(A const& v)
{
_a = v._a;
_b = v._b;
return *this;
}
int getA() const { return _a; }
int getB() const { return _b; }
using Policy::setA;
using Policy::setB;
private:
virtual void _setA(int a) { _a = a; }
virtual void _setB(int b) { _b = b; }
private:
int _a;
int _b;
};
int main(void)
{
std::vector<A<AllPolicy> > all_v(1, A<AllPolicy>(2, 3));
all_v[0].setA(1);
all_v[0].setB(2);
std::vector<A<APolicy> > a_v(1, A<APolicy>(2));
a_v[0].setA(1);
a_v[0].setB(2);
std::vector<A<BPolicy> > b_v(1, A<BPolicy>(1, 3));
b_v[0].setA(1);
b_v[0].setB(2);
}
Demo: http://www.ideone.com/mTJSb
So the idea is to use inheritance and the base class of A will expose what can be set. In the AllPolicy case, both methods are exposed, and in the other case one or other of the setters are exposed. A compiler error should result (as in the demo) if you try to use the opposite setter to the policy. Of course now A<APolicy> is not the same as A<BPolicy>, and if you wanted conversion, you'll have to provide conversion constructors etc.