I have a struct with two members, for example:
struct DataSet {
int x;
int y;
};
..., and i have to access those in a method, but only one at a time, for example:
void foo(StructMember dsm) { // ("StructMember" does not exist)
DataSet ds;
ds.x = 4;
ds.y = 6;
std::cout << ds.dsm * ds.dsm << std::endl;
}
foo(x);
foo(y);
Output i wish to have:
16
36
What should I do when I have to solve a problem like this? Is there a data type which can access a member?
Yes, you can use a pointer-to-member. The syntax for the type is TypeOfMember TypeOfStruct::*, and to access you do struct_variable.*pointer_variable
using StructMember = int DataSet::*; // Pointer to a member of `DataSet` of type `int`
void foo(StructMember dsm) {
DataSet ds;
ds.x = 4;
ds.y = 6;
std::cout << ds.*dsm * ds.*dsm << std::endl;
}
int main() {
foo(&DataSet::x);
foo(&DataSet::y);
}
Related
I have a bunch of derived structs. Is there any way for me to access the derived width without casting?
If I do this, I get 1s and not 42 and 13:
#include <iostream>
#include <deque>
using namespace std;
struct BaseParams {
virtual ~BaseParams() {}
int width = 1;
};
struct VectorParams : BaseParams {
int width = 42;
};
struct MatrixParams : BaseParams {
int width = 13;
};
int main()
{
std::deque<BaseParams *> params;
VectorParams *vectorParams = new VectorParams;
MatrixParams *matrixParams = new MatrixParams;
params.push_back(vectorParams);
params.push_back(matrixParams);
for (auto ¶m : params) {
std::cout << param->width << std::endl;
}
// Don't want to do this
// for (auto ¶m : params) {
// MatrixParams *matrixParams = dynamic_cast<MatrixParams *>(param);
// if (matrixParams)
// std::cout << matrixParams->width << std::endl;
// VectorParams *vectorParams = dynamic_cast<VectorParams *>(param);
// if (vectorParams)
// std::cout << vectorParams->width << std::endl;
// }
return 0;
}
If possible, I want to avoid casting because I have so many derived structs.
To overwrite the width in BaseParams, instead of making a new variable, you can give VectorParams a constructor like this:
struct VectorParams : BaseParams {
VectorParams() {
width = 42;
}
};
In fact constructors are always how variables are set in new objects. When you write
struct BaseParams {
virtual ~BaseParams() {}
int width = 1;
};
the compiler actually turns it into a constructor, similar to
struct BaseParams {
virtual ~BaseParams() {}
int width;
BaseParams() {
width = 1;
}
};
I'd like to have 2 different Data instances used in the client without either changing the static key in its member or resetting its member's value.
struct Data
{
static std::vector<int> vi;
};
struct DataUser
{
DataUser(int s) {
for (int i = 0; i < s; ++i)
{
Data::vi.emplace_back(i);
}
}
int getSize() { return Data::vi.size(); }
};
std::vector<int> Data::vi(0);
//.............. use it
int main()
{
{
DataUser d1(5);
std::cout << d1.getSize() << "\n";
}
{
DataUser d2(10);
std::cout << d2.getSize() << "\n";
}
}
e.g the output of the program is
5
15
I'd like it to be
5
10
static always means there is only one single instance of it in one binary.
The only way to have separate instances is to have a Data member and non static member in Data.
I created a class named result_line and have been having problems with it's constructor. That is that it wasn't being assigned the expected values.
I have since created a similar, but more frugal, class named rsltline and this appears to work.
Here's the 2 classes :-
result_line
class result_line {
private:
HWND rwnd;
int result_flags;
int result_extraflags;
public:
result_line(HWND, int, int);
~result_line();
HWND result_lineGetHWND();
void result_lineSetHWND(HWND);
int result_lineGetFlags();
int result_lineGetExtraFlags();
DINT result_lineGetBothFlags();
void result_lineSetFlags(int);
void result_lineSetExtraFlags(int);
void result_lineSetBothFlags(int,int);
void result_lineSetBothFlags(DINT);
};
// Constructor for result_line(HWND) and result_line(HWND, result_flag)
result_line::result_line(HWND rwnd, int result_flags, int result_extraflags) {
rwnd = rwnd;
result_flags = 30;
result_extraflags = 40;
}
result_line::~result_line() {}
HWND result_line::result_lineGetHWND() { return rwnd; }
int result_line::result_lineGetFlags() { return result_flags; }
int result_line::result_lineGetExtraFlags() { return result_extraflags; }
DINT result_line::result_lineGetBothFlags() { return DINT(result_flags,result_extraflags); }
void result_line::result_lineSetHWND(HWND rwnd) { rwnd = rwnd; }
void result_line::result_lineSetFlags(int result_flags) { result_flags = result_flags; }
void result_line::result_lineSetExtraFlags(int result_extraflags) { result_extraflags = result_extraflags; }
void result_line::result_lineSetBothFlags(int result_flags, int result_extraflags) {
result_flags = result_flags;
result_extraflags = result_extraflags;
}
void result_line::result_lineSetBothFlags(DINT dint) {
result_flags = dint.aint;
result_extraflags = dint.bint;
}
rsltline
class rsltline {
private:
HWND rlHWND;
int rlflag1;
int rlflag2;
public:
rsltline(HWND, int, int);
HWND rsltlineGetHWND();
int rsltlineGetFlag1();
int rsltlineGetFlag2();
};
rsltline::rsltline(HWND hwnd, int rf1, int rf2) {
rlHWND = hwnd;
rlflag1 = rf1;
rlflag2 = rf2;
}
HWND rsltline::rsltlineGetHWND() { return rlHWND; }
int rsltline::rsltlineGetFlag1() { return rlflag1; }
int rsltline::rsltlineGetFlag2() { return rlflag2; }
I have the following code to create and then display instances using the two classes (the last using the rsltline class as opposed to the result_line class, as used by the first two) :-
result_line foo = result_line(0,3,6);
std::cout << "HWND=" << foo.result_lineGetHWND() <<
"\tFLAGS=" << foo.result_lineGetFlags() <<
"\tEXTRAFLAGS=" << foo.result_lineGetExtraFlags() <<
std::endl;
result_line testrslt = result_line((HWND) 0,100,200);
std::cout << "HWND=" << testrslt.result_lineGetHWND() <<
"\tFLAGS=" << testrslt.result_lineGetFlags() <<
"\tEXTRAFLAGS=" << testrslt.result_lineGetExtraFlags() <<
std::endl;
rsltline myrsltline = rsltline((HWND)2,4,6);
std::cout << "HWND=" << myrsltline.rsltlineGetHWND() <<
"\tFLAGS=" << myrsltline.rsltlineGetFlag1() <<
"\tEXTRAFLAGS=" << myrsltline.rsltlineGetFlag2() <<
std::endl;
The first two return Unexpected Results, the last using the rsltline class works as expected. The results are:-
HWND=0 FLAGS=0 EXTRAFLAGS=0
HWND=0 FLAGS=1997196755 EXTRAFLAGS=0
HWND=0x2 FLAGS=4 EXTRAFLAGS=6
Process returned 0 (0x0) execution time : 35.007 s Press any key to
continue.
The only thing that I can think that may be causing this is the naming of the former. Although, perhaps it's simply a case of me needing to visit an optician :).
Lets take a closer look at the result_line constructor:
// Constructor for result_line(HWND) and result_line(HWND, result_flag)
result_line::result_line(HWND rwnd, int result_flags, int result_extraflags) {
rwnd = rwnd;
result_flags = 30;
result_extraflags = 40;
}
You declare a set of arguments, named rwnd, result_flags and result_extraflags. These are the same a local variables inside the constructor function body, and therefore shadows the member variables with the same name.
What happens is that you assign values to the local variables (the arguments), and not the member variables.
There are three solutions: Either use different names for the arguments, or prefix the member variables with this->, or use a constructor initializer list:
result_line::result_line(HWND rwnd, int result_flags, int result_extraflags)
: rwnd{rwnd}, result_flags{30], result_extraflags{40}
{
// Empty body
}
In the constructor body of result_line, you have written this:
rwnd = rwnd;
which is self-assignment of the parameter. The member remains uninitialized (like the other two members as well). You wanted to write this:
this->rwnd = rwnd;
That is one problem I can see in your code, which can be fixed as above — however, it is best to use member-initialization-list:
result_line::result_line(HWND rwnd, int result_flags, int result_extraflags)
: rwnd(rwnd),
result_flags(result_flags),
result_extraflags(result_extraflags)
{
}
Here, members are initialized in the form of X(Y) — X is a member and Y is a parameter; X and Y could be the same name, but they would continue to represent what they are — member and parameter.
This question probably only makes sense for people with knowledge on programming languages supporting closures. If you don't, please do not comment "why would you like to do this?": there are tons of legitimate reasons to do that.
It is common in functional languages to define local functions that capture the already defined local variables. In C++, that would look like (but of course is illegal):
#include <iostream>
using namespace std;
int main()
{
int x = 0;
int f() { return x + 1; }
cout << f() << endl; // would print 1
x = 2;
cout << f() << endl; // would print 3
}
To allow this, C++11 introduces lambda functions, so it is actually possible to do it in a rather nice way (though, not as nice as it generally is in functional languages ;-) ):
#include <iostream>
using namespace std;
int main()
{
int x = 0;
auto f = [&] () { return x + 1; };
cout << f() << endl; // actually compiles and prints 1
x = 2;
cout << f() << endl; // actually compiles and prints 3
}
My question is: now that it is possible to automatically capture free variables by reference for functions, wouldn't that be nice to be possible to do for locally defined structs? Ideally, I would love to be able to write:
int main()
{
int x = 0;
struct A
{
int y;
A(int y) : y(y) {}
int f() { return x + y; };
};
A a1(1);
A a2(2);
cout << a1.f() << endl; // would print 1
cout << a2.f() << endl; // would print 2
x = 2;
cout << a1.f() << endl; // would print 3
cout << a2.f() << endl; // would print 4
}
The only workaround I've found is to manually pass as argument to the constructor all the non-local (free) variables, which is a bit of a pain when there are plenty of them:
#include <iostream>
using namespace std;
int main()
{
int x = 0;
struct A
{
// meaningful members
int y;
int f() { return x + y; };
// free variables
int & x;
// Constructor
A(
// meaningful arguments
int y,
// capturing free variables
int & x
) : y(y), x(x) {}
};
A a1(1, x);
A a2(2, x);
cout << a1.f() << endl; // prints 1
cout << a2.f() << endl; // prints 2
x = 2;
cout << a1.f() << endl; // prints 3
cout << a2.f() << endl; // prints 4
}
Do you know of any other workaround that would avoid manually passing as argument all free variables, or do you know if these kind of "environment-aware" locally-defined structs are considered for future extensions of C++? (i.e., C++1y?)
What you ask for is not available, but you can get similar results by combining functions with a combination of lambdas and binders:
auto lambda = [](int i) { return x+i; };
auto a1 = std::bind(lambda,1);
auto a2 = std::bind(lambda,2);
Depending on the amount and shape of changes, you could invert the solution and have a struct that takes the lambda with the capture and then adds it's own logic.
I don't find this particularly beautiful, and I'm not entirely sure it's compliant, but neither g++ nor clang++ complains about this:
#include <iostream>
int main()
{
int x = 1;
auto l = [&](int p){
auto ll0 = [&, p]{ return p + x + 5; };
auto ll1 = [&, p]{ return p + x * 2; };
struct
{
decltype(ll0) l0;
decltype(ll1) l1;
} ret{ll0, ll1};
return ret;
};
std::cout << l(42).l0() << '\n';
auto lo = l(21);
std::cout << lo.l1() << '\n';
}
I think the creation of the unnamed struct could possibly be automated by a macro.
The lambda expressions of C++ are the capturing mechanism and inline object literals of a sort. Depending on your exact purpose, they may be more convenient than a local struct definition.
As a motivating example, consider the following:
// environment
int offset = 42;
struct local_type {
// capture environment 'by-hand'
int offset;
// purpose of the local type is to expose two overloads
int operator()(int x) const
{ return x + offset; }
double operator()(double x) const
{ return x + offset; }
} f { offset };
You can turn this on its head by doing:
int offset = 42;
auto f = make_overload([=](int x) { return offset + x; },
[=](double x) { return offset + x; });
The lambda expressions take care of capturing, the make_overload combinator takes care of building the desired object -- here, one that has an overloaded operator(). (It would be implemented best by making use of inheritance.)
This approach makes sense if you know that you'll (re)use make_overload from various places. For one-time, special uses there's no avoiding writing a specialty type, whether local or not.
class Foo {
public:
Foo() { do_something = &Foo::func_x; }
int (Foo::*do_something)(int); // function pointer to class member function
void setFunc(bool e) { do_something = e ? &Foo::func_x : &Foo::func_y; }
private:
int func_x(int m) { return m *= 5; }
int func_y(int n) { return n *= 6; }
};
int
main()
{
Foo f;
f.setFunc(false);
return (f.*do_something)(5); // <- Not ok. Compile error.
}
How can I get this to work?
class A{
public:
typedef int (A::*method)();
method p;
A(){
p = &A::foo;
(this->*p)(); // <- trick 1, inner call
}
int foo(){
printf("foo\n");
return 0;
}
};
void main()
{
A a;
(a.*a.p)(); // <- trick 2, outer call
}
The line you want is
return (f.*f.do_something)(5);
(That compiles -- I've tried it)
"*f.do_something" refers to the pointer itself --- "f" tells us where to get the do_something value from. But we still need to give an object that will be the this pointer when we call the function. That's why we need the "f." prefix.
class A {
int var;
int var2;
public:
void setVar(int v);
int getVar();
void setVar2(int v);
int getVar2();
typedef int (A::*_fVar)();
_fVar fvar;
void setFvar(_fVar afvar) { fvar = afvar; }
void insideCall() { (this->*fvar)(); }
};
void A::setVar(int v)
{
var = v;
}
int A::getVar()
{
std::cout << "A::getVar() is called. var = " << var << std::endl;
return var;
}
void A::setVar2(int v2)
{
var2 = v2;
}
int A::getVar2()
{
std::cout << "A::getVar2() is called. var2 = " << var2 << std::endl;
return var2;
}
int main()
{
A a;
a.setVar(3);
a.setVar2(5);
// a.fvar = &A::getVar;
a.setFvar(&A::getVar);
(a.*a.fvar)();
a.setFvar(&A::getVar2);
(a.*a.fvar)();
a.setFvar(&A::getVar);
a.insideCall();
a.setFvar(&A::getVar2);
a.insideCall();
return 0;
}
I extended Nick Dandoulakis's answer. Thank you.
I added a function which set the member function pointer from outside of the class. I added another function which can be called from outside to show inner call of member function pointer.
Try (f.*do_something)(5);
#include<iostream>
using namespace std;
class A {
public:
void hello()
{
cout << "hello" << endl;
};
int x = 0;
};
void main(void)
{
//pointer
A * a = new A;
void(A::*pfun)() = &A::hello;
int A::*v1 = &A::x;
(a->*pfun)();
a->*v1 = 100;
cout << a->*v1 << endl << endl;
//-----------------------------
A b;
void(A::*fun)() = &A::hello;
int A::*v2 = &A::x;
(b.*fun)();
b.*v2 = 200;
cout << b.*v2 << endl;
}
I think calling a non static member of the class could also be done using a static member function.