I fear it's a dumb question but...
Someone can suggest me a way to force that a return value from a function (or a method), that return a reference to an internal static variable or a member of the class/struct, is assigned only to reference variables ?
I try to explain what I desire with a minimal example.
Given the following code, with a function wrapValue() that return a reference to the internal static variable,
int & wrapValue (int v0)
{
static int val;
return val = v0;
}
int main ()
{
// how to permit this ...
int & v0 { wrapValue(0) };
// ... but forbid this ...
int v1 { wrapValue(1) };
int v2;
// ... and this ?
v2 = wrapValue(2);
}
there is a way to permit the initialization of v0 (and bound v0 to the static variable) and forbid the initialization of v1 and the assignment of v2 (without bounding v1 and v2 to the static variable) ?
And if it's impossible with the current C++ standard, as I fear, someone can suggest me an alternative way (but not too complex: I intend use it in a library that I want to maintain simple) to forbid an unbounded assignment ?
This solution is somewhat tricky but it works (I think) as you expect:
#include <iostream>
struct int_wrapper {
int value;
int_wrapper &operator=(int value) {
this->value = value;
return *this;
}
operator int&() {
return value;
}
operator int() {
return value;
}
};
int_wrapper& wrapValue (int v0) {
static int_wrapper val;
return val = v0;
}
int main () {
// how to permit this ...
int & v0 = wrapValue(0);
// ... but forbid this ...
//int v1 { wrapValue(1) }; // call ambigious
int v2;
(void)v0;
(void)v2;
// ... and this ?
//v2 = wrapValue(2); // call ambigious
}
[live demo]
As far as I know int is copyable, so people can copy if they like; you cannot prevent this. However, you could create a wrapper class that is non-copyable.
class NonCopyableInt
{
int val;
public:
NonCopyableInt(int val) : val(val) {}
NonCopyableInt(NonCopyableInt&) = delete;
int& value() { return val; }
// todo: add some nice operators and functions such as assignment from int
}
NonCopyableInt& wrapValue (int v0)
{
static NonCopyableInt val;
return val = v0;
}
However, people could always copy the return value from value() so you end up with the same problem. And it feels really clunky and meh.
Related
I have been looking to change dynamically the values of an array in a struct depending on other variables of the struct.
Let's say I have:
struct foo
{
int value1 = 0;
int value2 = 0;
int arr[2] = {value1, value2};
};
In the main if I have create an instance fooInstance and I want to associate a value to value1 fooInstance.value1 = 10, how can I update the value in the array ?
Thank you for your time.
Firstly, if you need an array, then I recommend storing the objects in the array directly.
I question the value (i.e. usefulness) of these aliases such as value1 when the name has no more meaning than referring to arr[i] directly. But I can see the value in case there is a descriptive name available. I'll use a more meaningful example of 2D vector with x, y dimensions. It should be easy to change float to int and change the names to match your attempt.
While Frank's solution using functions is great in most regards, it has a small caveat of having a less convenient syntax compared to variables. It's possible to achieve the variable syntax using operator overloading and anonymous unions. The trade-off is the increased boilerplate in the class definition. Example:
union Vector2 {
struct {
float a[2];
auto& operator=(float f) { a[0] = f; return *this; }
operator float&() & { return a[0]; }
operator const float&() const & { return a[0]; }
operator float () && { return a[0]; }
float* operator&() { return &a[0]; }
} x;
struct {
float a[2];
auto& operator=(float f) { a[1] = f; return *this; }
operator float&() & { return a[1]; }
operator const float&() const & { return a[1]; }
operator float () && { return a[1]; }
float* operator&() { return &a[1]; }
} y;
struct {
float a[2];
auto& operator=(float f) { a[0] = a[1] = f; return *this; }
float* begin() { return std::begin(a); }
float* end() { return std::end(a); }
} xy;
};
int main() {
Vector2 v2;
v2.xy = 1337; // assign many elements by name
v2.x = 42; // assign one element by name
std::cout << v2.x; // read one element by name
for(float f : v2.xy) { // iterate the entire array
std::cout << f;
}
}
Note to those unfamiliar with rules of unions: Reading from inactive union member is allowed only through common initial sequence of standard layout structs. This code is well defined, but the reader should be careful to not over generalise and assume that type punning through unions would be allowed; It isn't.
I adapted code from my earlier answer to another question.
It is different parameters coming from different hardwares.
This sounds like generating the accessors shown above with meta programming could be a good approach.
But, if you would like to avoid the complexity, then a more traditional approach would be to just use the array, and use enum to name the indices:
struct foo
{
int arr[100];
enum indices {
name1,
name2,
// ...
name100,
name_count,
};
};
int main()
{
foo f;
f.arr[foo.name1] = 42;
}
If at all possible, use encapsulation. That's the preferred way to create an interface/implementation skew:
struct foo
{
int& value1() { return arr_[0]; }
int& value2() { return arr_[1]; }
int* arr() { return arr_; }
private:
int arr_[2] = {0, 0};
};
void bar(foo& v) {
// access a single value
v.value1() = 3;
// access the whole array
v.arr()[0] = 5;
}
If you need access through both the individual member variables and through an array member variable, do not copy the data; rather, use the array as "the source of truth", and provide access through the individual variables or the individual member functions.
Here is your example rewritten to "alias" array variables to scalar member variables:
struct foo
{
foo() : value1(arr[0]), value2(arr[1]) {}
std::array<int,2> arr;
int& value1;
int& value2;
};
Note: this is not a good way of doing anything in production code, just an illustration of how the language lets you do something like this. Normally I would add accessor member-functions instead of member-variable references, because it avoids many problems referenced in the comments, such as breaking the value semantics.
I'm working on a snake game program. I use a deque of Body in class Snake to represent a snake and of course Body is a struct I have defined. Here is part of the code:
struct Body { // one part of snake body
int x, y, direction;
Body() : x(0), y(0), direction(UP) { }
Body(int ix, int iy, int id) : x(ix), y(iy), direction(id) { }
};
class Snake {
protected:
std::deque<Body> body;
// other members
public:
auto begin()->std::deque<Body>::const_iterator const { return body.cbegin(); }
auto end()->std::deque<Body>::const_iterator const { return body.cend(); }
// other members
};
And in another function construct_random_food I need to generate a food and make sure it does not coincide with the snake. Here's the function definition:
Food construct_random_food(int gameSize, const Snake& snake) {
static std::random_device rd;
static std::uniform_int_distribution<> u(2, gameSize + 1);
static std::default_random_engine e(rd());
Food f;
while (1) {
f.x = u(e) * 2 - 1;
f.y = u(e);
bool coincide = 0;
for (const auto& bd : snake) // This causes an error.
if (bd.x == f.x && bd.y == f.y) {
coincide = 1; break;
}
if (!coincide) break;
}
return f;
}
An error is caused at the range-based for-loops line. It says that I'm trying to cast const Snake to Snake& (casting a low-level const away). I fix the problem by rewriting that line like this:
for (const auto& fd : const_cast<Snake&>(snake))
So I'm wondering what exactly a range-for do and what it needs. Does the error have anything to do with the begin() function in class Snake?
The problem is that your begin and end functions are not const.
auto begin()->std::deque<Body>::const_iterator const { return body.cbegin(); }
// this applies to the return type ^^^^^
You've applied the const qualifier to the return type, not to the calling object. Put the const qualifier before the trailing return type.
auto begin() const ->std::deque<Body>::const_iterator { return body.cbegin(); }
You can see the correct order in which you should place function qualifiers here: http://en.cppreference.com/w/cpp/language/function
I want to have thread safe indexing operator and I came with the following code which seems to work.
Can you see any problems with it except for bounds checking?
Is there a better way to do the same thing (with overloading indexing operator, not with get/set functions)?
class A
{
public:
A()
{
for (auto i = 0; i < 100; ++i)
{
v[i] = i + 1;
}
};
class Proxy
{
int* val;
A* parent;
public:
Proxy(int& a, A* p) : parent(p)
{
parent->z.lock();
val = &a;
};
~Proxy()
{
parent->z.unlock();
}
int operator=(int a)
{
*val = a;
return a;
};
operator int() const
{
return *val;
};
};
int operator[](int i) const
{
z.lock();
int r = v[i];
z.unlock();
return r;
}
Proxy operator[](int i)
{
return Proxy(v[i], this);
}
int v[100];
Z z; // some locking mechanism, not important
};
Since the locking mechanism isn't specified I'd assume it uses a normal mutex in which case the obvious problem is this:
A a;
a[0] = a[1];
Put differently, it is very easy to dead-lock the program. This problem is avoided with recursive mutexes.
The other obvious problem is that the code depends on copy-elision which is not guaranteed to always happen. If the copy is not elided upon return the temporary will release the lock and the copy will release it again which normally is undefined behavior. In addition, access to the member is unguarded and will potentially introduce data races. To avoid this problem you should define a move constructor and make sure that the moved from state doesn't try to release the mutex, e.g.:
A::Proxy::Proxy(Proxy&& other)
: val(other.val)
, parent(other.parent) {
other.parent = 0;
}
A::Proxy::~Proxy() {
if (parent){
parent->unlock();
}
}
The not so obvious issue is that it is unlikely to result in an efficient implementation.
After having produced some code in C++, it may be necessary to change the access to a member of a structure or class to something that produces some side effects. In that sense we would need to overload the assignement of a member to something different.
Struct A{
int v;
}
int main(){
A a;
a.v=17;
}
Is there the possibility to do it somehow ?
If there is not the possibility how would had been written the code in order to allow the flexibility to change a member into something more ?
The possibility of having each access to a memeber divided into a getter and setter seems coumbersome and impractical for any reasonable use.
Yes, use a proxy:
struct A
{
v_proxy v;
private:
struct v_proxy
{
v_proxy( int vv = 0 ) : v{ vv }
{}
//Write access
v_proxy& operator=( int i )
{
//Put your new code here
return v = i;
}
//Read access
operator int() const
{
return v;
}
int v;
};
};
int main()
{
A a;
a.v = 0;
};
Writting a generic proxy like this to allow the customization of read/writes in a common non- get/set syntax is easy.
EDIT: Some claim that this doesn't mimic correctly the behaviour of a C# property since in C# we can access this from the properties. Ok, just add a reference to the object and pass it to the proxy ctor. And don't forget to make the proxy class a friend of your class, to give that this reference full access:
class A
{
A() : v{ *this }
{}
friend struct v_proxy
{
v_proxy( A& ref , int vv = 0 ) : v{ vv } , This{ std::ref( ref )
{}
//Write access
int& operator=( int i )
{
//Put your new code here, for example:
This.foo();
return v = i;
}
//Read access
operator int() const
{
return v;
}
int v;
private:
std::reference_wrapper<A> This;
};
In C++,
function() = 10;
works if the function returns a variable by reference.
What are the use cases of it?
The commonest case is to implement things like operator[].
struct A {
int data[10];
int & operator[]( int i ) {
return data[i];
}
};
Another is to return a big object from a class via an accesor function:
struct b {
SomeBigThing big;
const SomeBigThing & MyBig() const {
return big;
}
};
in order to avoid the copying overhead.
Consider the following code, MyFunction returns a pointer to an int, and you set a value to the int.
int *i;
i = MyFunction();
*i = 10;
Now shorten that to
*(MyFunction()) = 10;
It does exactly the same thing as the first code block.
You can look at a reference as just a pointer that's always dereferenced. So if my function returned a reference - not a pointer - to an int the frist code block would become
int &i;
i = MyFunction();
i = 10;
and the second would become
MyFunction() = 10;
This is what i was looking for
Getters/setters for instance
class C
{
int some_param_;
public:
int& param() { return some_param_; }
int const& param() const { return some_param_; }
};
but here you should go with some_param being a public int. Containers provide functions that return by reference, eg. vector<T>::operator[] so that you can write v[k] = x.
A very normal use case is when you write an array like class. Here you want to overload the operator [] so as you can do a[0] = 10; In that case you would want the signature to be like int& operator[](int index);
In case you have a class that contains another structure, it can be useful to directly modify the contained structure:
struct S
{
int value;
};
class C
{
public:
S& ref() { return m_s; }
private:
S m_s;
};
Allows you to write something like:
void foo()
{
C c;
// Now you can do that:
c.ref().value = 1;
}
Note: in this example it might be more straightforward to directly make m_s public rather than returning a reference.
SO screwed up my answer
You don't even need to return a reference:
struct C { };
C f() {
return C();
}
int main() {
C a;
f() = a; // compiles fine
}
Because this behavior is quite surprising, you should normally return a const value or a const reference unless the user has a sensible intent to modify the result.
It can be usefull when implementing accessors
class Matrix
{
public:
//I skip constructor, destructor etc
int & operator ()(int row, int col)
{
return m_arr[row + col * size];
}
private:
int size;
int * m_arr;
}
Matrix m(10);
m(1,0) = 10; //assign a value to row 1, col 0
Another classic case:
class Foo {
Foo();
public:
static Foo& getSingleton();
};
std::vector has operator[] which would not allow vec[n] = m otherwise.
You can also achieve method chaining (if you so desire) using return by reference.
class A
{
public:
A& method1()
{
//do something
return *this; //return ref to the current object
}
A& method2(int i);
A& method3(float f); //other bodies omitted for brevity
};
int main()
{
A aObj;
aObj.method1().method2(5).method3(0.75);
//or use it like this, if you prefer
aObj.method1()
.method2(5)
.method3(0.75);
}
The named parameter idiom is a another use case. Consider
class Foo
{
public:
Foo(
int lions,
float tigers,
double bears,
std::string zookeeper
);
};
users of this class need to remember the position of each parameter
Foo foo( 1, 2.0, 5, "Fred" );
which can be non-obvious without looking at the header. Compared to a creator class like so
class CreateFoo
{
friend class Foo;
public:
CreateFoo();
CreateFoo& lions(int lions) {
_lions = lions;
return *this;
}
CreateFoo& tigers(float tigers) {
_tigers = tigers;
return *this;
}
CreateFoo& bears(double bears) {
_bears = bears;
return *this;
}
CreateFoo& zookeeper(const std::string& zookeeper) {
_zookeeper = zookeeper;
return *this;
}
private:
int _lions;
float _tigers;
double _bears;
std::string _zookeeper;
};
which can then be used by clients like so
Foo foo = CreateFoo().
lions(1).
tigers(2.0).
zookeeper("Fred").
bears(5)
;
assuming Foo has a constructor taking a const CreateFoo&.