I want to track when a particular member variable changes value so I can print it out. Now, the obvious solution to do this is to add a tracking function in the member's Set method, like so :
class Foo
{
public:
Foo() {}
void SetBar(int value)
{
//Log that m_bar is going to be changed
m_bar = value;
}
private:
int m_bar; // the variable we want to track
};
The problem I'm facing is that I'm working on a huge project and some classes have a lot of methods that internally change member variables instead of calling their Setters.
m_bar = somevalue;
Instead of :
SetBar(somevalue);
So I'm wondering if there's a faster/more clean method to achieve what I want than just changing every m_bar = to SetBar(. An assignment operator overload only for that member variable perhaps?
If it is possible for you to change the data type of the member, you can change it to a logger type.
Example:
#include <iostream>
template <class T>
class Logger
{
T value;
public:
T& operator=(const T& other)
{
std::cout << "Setting new value\n";
value = other;
return value;
}
operator T() const
{
return value;
}
};
class Foo
{
public:
Foo() {}
void SetBar(int value)
{
//Log that m_bar is going to be changed
m_bar = value;
}
private:
#if 1
Logger<int> m_bar; // the variable we want to track
#else
int m_bar; // the variable we want to track
#endif
};
int main()
{
auto f = Foo();
f.SetBar(12);
}
Online example at ideone.
Related
Hi I am trying to have a getter in my class that returns a "read-only" reference to a vector of objects. Each of those objects its own variables and functions, that I need to call. The way that I am trying to set this up is to have the getter in the main class return a const reference. However, I don't seem to be able to access the values of the objects held in the vector. Is there a better way to do this? Here is a smallest reproducible example. Thank you.
#include <vector>
class Obj
{
private:
int val;
public:
Obj() { val = 10; }
inline int getVal() { return val; }
};
class Foo
{
private:
std::vector<Obj> obsVec;
public:
Foo()
{
Obj a;
Obj b;
obsVec.push_back(a);
obsVec.push_back(b);
}
const std::vector<Obj>& getConstRef() const { return obsVec; }
};
int main()
{
Foo foo;
foo.getConstRef()[0].getVal(); // Here is where I get the error
return 0;
}
The error that I get is:
Error (active) E1086 the object has type qualifiers that are not compatible with the member function "Obj::getVal"
You need to declare getVal() as const:
inline int getVal() const { return val; }
instead of:
inline int getVal() { return val; }
foo.getConstRef()[0] returns const A &, but getVal is not marked const.
Also note that inline is useless here, since functions defined (rather than declared) in class body are implicitly inline.
I am working on a plugin that runs inside a host program against a proprietary PDK. At times there will be breaking changes in the PDK, so my code uses wrapper classes that allow it to work with more than one version of the host while encapsulating the changes from version to version.
Here is a very simplified example that illustrates the kind of issue I would like to address. Of course, I'm dealing with many more members that 2.
struct DataV1 // I cannot modify this
{
int a;
float b;
};
struct DataV2 // I cannot modify this
{
float b;
int a;
long c;
};
class DataWrapper // my class
{
private:
bool _forV1; // determined at run-time
DataV1 _dataV1;
DataV2 _dataV2;
public:
DataWrapper(); // initializes _forV1
int GetA() const;
void SetA(int value);
float GetB() const;
void SetB(float value);
long GetC() const { return _dataV2.c } // only exists in v2
void SetC(long value) { _dataV2.c = value; } // only exists in v2
};
I would like to avoid duplicating in every getter and setter the logic that chooses the member from one version of the struct or the other. Note that while the order of members is rearranged, the types and member names are the same. I came up with this macro:
#define DATA_ACCESS(MEMBER) const_cast<decltype(_dataV1.MEMBER)&>(([&]() -> const decltype(_dataV1.MEMBER)& \
{ return (_forV1) ? _dataV1.MEMBER : _dataV2.MEMBER; })())
This allows for a somewhat elegant implementation of the property accessor functons:
int GetA() const { return DATA_ACCESS(a); }
void SetA(int value) { DATA_ACCESS(a) = value; }
float GetB() const { return DATA_ACCESS(b); }
void SetB(float value) { DATA_ACCESS(b) = value; }
I am posting this question to see if anyone has a better idea, especially an idea that doesn't involve a macro. Thanks.
With std::variant, you might do something like:
class DataWrapper // my class
{
private:
std::variant<DataV1, DataV2> data;
public:
DataWrapper(); // initializes _forV1
int GetA() const { return std::visit([](auto& arg){ return arg.a; }, data); }
void SetA(int a) const { std::visit([&a](auto& arg){ arg.a = a; }, data); }
// ...
};
In C++ is there a way, using raw pointers or otherwise to trigger some action when the pointed to object changes?
Scenario:
class A
{
double var;
B var2 {&var};
}
class B
{
double* pVar;
B (double* _var ) { pVar = _var};
}
I have functions inside class B that will get called whenever member variable var changes value. At the moment I would need these functions to be public so they can be called manually from class A, this could be achieved by using a setter for var. If I wanted to keep the function inside class B private (as it is called by other events internal to class B) what are my options?
This is an example of the observer pattern.
So what you need is to trigger a function call to another object
when the value of your object is changed through a setter method.
#include <functional>
#include <iostream>
//-----------------------------------------------------------------------------
// the class with the member variable that can change
// and to which another class can react.
// This is a simple example where only one "callback" function
// can be registered. In the typical observer pattern
// there can be multiple callbacks registered.
class Observee
{
public:
// set notification function to a function that does nothing
// "null strategy pattern"
Observee() :
m_notify_observer_fn{ [](int) {} }
{
}
// let another object pass in a function that will be called
// when the value is changed
void OnValueChanged(std::function<void(int)> notify_observer_fn)
{
m_notify_observer_fn = notify_observer_fn;
}
// to change the member value AND notify the other object
// that the value has changed we need a setter function.
void set_value(int value)
{
// check if the value really has changed
if (m_value != value)
{
// set the member value
m_value = value;
// then notify the observer of the new value
// by calling the notification function
m_notify_observer_fn(m_value);
}
}
private:
std::function<void(int)> m_notify_observer_fn;
int m_value{};
};
//-----------------------------------------------------------------------------
// The class that wants to get a notification when the value
// of the other class changes (role is an Observer)
class Observer
{
public:
explicit Observer(Observee& observee)
{
// Set the callback in the observee to the OnValueChanged
// function of this object (the function passed is called a lambda funtion)
observee.OnValueChanged([this](int value)
{
OnValueChanged(value);
});
}
private:
void OnValueChanged(int value)
{
std::cout << "Value changed to " << value << "\n";
}
};
//-----------------------------------------------------------------------------
int main()
{
// make instances of both classes.
Observee observee;
Observer observer{ observee };
// now set the value
// this will change the member in observee
// and then call the method in the observer for you
observee.set_value(42);
return 0;
}
Question : If I wanted to keep the function inside class B private (as it is called by other events internal to class B) what are my options?
You can call a private function of class B while coding class A using friend attribute.
class B
{
friend class A;
private:
void foo() { std::cout << "using foo." << std::endl; }
};
class A
{
private:
B b;
public:
void bar(){ b.foo(); }
};
int main()
{
A a;
a.bar();
return 0;
}
About the callback to be call when a double variable change its value:
No you can't do it with a raw pointer.
You got at least two ways of doing it.
The first way is what you outlined : use a setter function.
The second is to make a class that own the value and that overloading operator= is able to call the callback.
I'll sketch something here to make you understand better:
template<class T>
class Owner{
using FuncType = std::function<void(Owner<T>&)>;
public:
Owner(){}
Owner(const T& init){
_var = init;
}
Owner(const Owner<T>& init){
_var = init;
}
operator T(){
return _var;
}
auto& operator =(const T& rvalue){
_var = rvalue;
_on_change();
return *this;
}
auto& operator =(const Owner<T>& rvalue){
_var = rvalue;
_on_change();
return *this;
}
const T& get() const { //don't make it non const or
//you will lose ownership to value of _var
return _var;
}
void set(const T& val){
_var = val;
_on_change();
}
void set(const Owner<T>& val){
_var = val;
_on_change();
}
void set_handler(FuncType func)
{
_func = func;
}
private:
void _on_change(){
if(_func)
_func(*this);
}
private:
T _var{};
FuncType _func{};
};
int main()
{
Owner<double> var{};
var.set_handler([](Owner<double>& ch){
std::cout << "Value changed: " << (double) ch << std::endl;
});
var = 1.0;
return 0;
}
Suppose I have a class in C++11 like this:
class Something
{
...
private:
class1* a;
class2* b;
class3* c;
public:
class1* reada() { return a; }
class2* readb() { return b; }
class3* readc() { return c; }
void customFunctionForclass1();
void customFunctionForclass2();
void customFunctionForclass3();
}
}
I'd like to make the read functions templated so that if another programmer adds another member class, the corresponding read function will be template-magic created.
Something like this maybe?
class Something
{
...
private:
templateContainer = {class1*,class2*,class3*}
template<thing in templateContainer>
thing variableOfTypeThing;
public:
template<thing in templateContainer>
<thing> read() {return variableOfTypeThing<thing>;}
void customFunctionForclass1();
void customFunctionForclass2();
void customFunctionForclass3();
}
As you can tell from the example, I'm confused.
Basically, I have a class which acts as a container for guaranteed unique class variables (no class1 A; class1 B)
Some function groups for the class are almost identical some function groups are highly varied. It would be great for future people to only have to modify the different parts of the class and get the rest from the templates.
I thought maybe there would be a way by splitting this class up into lots of classes and stuffing them into an array of void pointers, but that seems unwise.
Suggestions?
I'd like to make the read functions templated so that if another programmer adds another member class, the corresponding read function will be template-magic created.
You could encapsulate the user defined classes in a thin wrapper class with a read() function that returns the contained instance. Adding a user defined class to Something would then be done by inheriting wrapper<user_defined_class>.
Basically, I have a class which acts as a container for guaranteed unique class variables
Inheriting this wrapper prevents you from including the same class twice so it could possibly be a way forward:
#include <iostream>
// the "thing" wrapper
template<typename T>
struct thing {
// forward construction arguments to the contained variable
template<class... Args>
thing(Args&&... args) : variable(std::forward<Args>(args)...) {}
// basic interface, const and non-const. I called it get() instead of read()
T const& get() const { return variable; }
T& get() { return variable; }
private:
T variable;
};
// a troublesome user defined class that is not default constructibe :-(
struct user_defined {
user_defined() = delete; // silly example really, but it's just to demonstrate
user_defined(const std::string& v) : str(v) {}
user_defined& operator=(const std::string& v) {
str = v;
return *this;
}
std::string const& say() const { return str; }
private:
std::string str;
};
std::ostream& operator<<(std::ostream& os, const user_defined& ud) {
return os << ud.say();
}
// ... and the "Something" class that inherits the wrapped types.
class Something : thing<int>,
thing<double>,
thing<user_defined>
{
public:
// add initial values for types that are not default constructible
Something(const std::string& val) : thing<user_defined>(val) {}
Something() : Something("") {} // default ctor
// access via derived class, const and non-const
template<typename T>
T const& get() const {
return thing<T>::get(); // get() from the correct base
}
template<typename T>
T& get() {
return thing<T>::get(); // get() from the correct base
}
};
void print(const Something& s) {
// using the const interface
std::cout << s.get<int>() << "\n";
std::cout << s.get<double>() << "\n";
std::cout << s.get<user_defined>() << "\n";
}
int main() {
Something foo;
// using the non-const interface to set
foo.get<int>() = 10;
foo.get<double>() = 3.14159;
foo.get<user_defined>() = "Hello world";
print(foo);
}
Edit: It doesn't fulfill the index part of your question though. You access it using the type you'd like to get() as a tag. You basically build a very rudimentary tuple I guess.
Code based on #Ted Lyngmo's answer:
#include <iostream>
#include <string>
template<typename T>
struct thing {
// forward construction arguments to the contained variable
template<class... Args>
thing(Args&&... args) : variable(std::forward<Args>(args)...) {}
// basic interface, const and non-const. I called it get() instead of read()
T const& get() const { return variable; }
T& get() { return variable; }
protected:
T variable;
};
template<typename ...Ts>
struct things : thing<Ts>... {
template<class... SubTs>
things(thing<SubTs>&&... ts) : thing<SubTs>(std::move(ts))... {}
// access via derived class, const and non-const
template<typename T>
T const& get() const {
return thing<T>::get(); // get() from the correct base
}
template<typename T>
T& get() {
return thing<T>::get(); // get() from the correct base
}
};
// a troublesome user defined class that is not default constructibe :-(
struct user_defined {
user_defined() = delete; // silly example really, but it's just to demonstrate
user_defined(const std::string& v) : str(v) {}
user_defined& operator=(const std::string& v) {
str = v;
return *this;
}
std::string const& say() const { return str; }
private:
std::string str;
};
struct non_default {
non_default() = delete;
non_default(int) {}
};
std::ostream& operator<<(std::ostream& os, const user_defined& ud) {
return os << ud.say();
}
// ... and the "Something" class that inherits the wrapped types.
class Something : public things<int, double, user_defined, non_default>
{
public:
// add initial values for types that are not default constructible
Something(const std::string& val) : things(thing<user_defined>(val), thing<non_default>(0)) {}
Something() : Something("") {} // default ctor
};
void print(const Something& s) {
// using the const interface
std::cout << s.get<int>() << "\n";
std::cout << s.get<double>() << "\n";
std::cout << s.get<user_defined>() << "\n";
}
int main() {
Something foo;
// using the non-const interface to set
foo.get<int>() = 10;
foo.get<double>() = 3.14159;
foo.get<user_defined>() = "Hello world";
print(foo);
}
I need someone to show me what is wrong with this code. I don't know what's wrong with it. I know the code doesn't do anything meaningful and it can't be used. I created it only to know how copy constructors work.
class test
{
public:
int* value;
public:
int getvalue()
{return *value;};
test(int x){ value = new int(x);};
test(const test& a)
{
value=new int;
*value = a.getvalue();
};
};
You need to change the declaration of getvalue() to int getvalue() const, since you're trying to call getvalue() on a const reference in your copy constructor.
There is a stray ; after each method definition, so will not compile.
class test { public:
int* value;
public:
int getvalue()
{return *value;}
test(int x){ value= new int(x);}
test(const test& a)
{
value=new int;
*value = a.getvalue();
}
};
Also, I'd avoid 'test' as a class name; depending on your platform if might be a macro or some other in-scpe name. Use "MyTest" or somesuch.
It's been a long time since I last wrote C++, but here goes:
I'm not sure why you're declaring value to be an int pointer; did you mean to make it an int?
class test
{
private:
int value;
public:
test(int x)
{
value = new int(x);
}
int getValue()
{
return value;
}
test(const test & a)
{
value = a.getValue();
}
};
(Posted on behalf of the OP).
I tried making the getvalue() function const and it worked. The problem was that I passed the test class as a const reference and because I didn't declare the getvalue() function const the compiler thought the function was going to change something in that reference.