I do not think "in place" is the right term, but I am lacking a better one.
I have a POD, let's say:
struct My {
int a;
};
//and suppose a operator<< to stream is also defined
And I may use it right this:
My my = {3};
std::cout << my << std::endl;
I am wondering if I can do the same below but without using a helper func:
template <typename ANY>
My helper(ANY value) {
My r = {value};
return r;
}
std::cout << helper(3) << std::endl;
I am looking for the same thing that a constructor does, but since I have a POD I can not create a constructor.
You can do this:
struct My {
int a;
int b;
int c;
float d;
};
void somefunc() {
cout << (My){1, 2, 3, 4.5} << endl;
}
Related
I have a struct with some other structs as member. Both external and internal structs are StandardLayout (it can be even assumed that internal are plain old data). Something like this:
struct Inner1 {
int a = 0, b = 0;
};
struct Inner2 {
int c = 0, d = 0;
};
struct Outer {
Inner1 x;
std::string s;
Inner2 y;
};
I want to write some function that takes Outer& and object of some type T that can return value of any nested field, depending on argument:
int get(Outer& o, T field);
If Outer was a flat structure, pointers to member would be exactly what I needed, however it is not flat.
The trivial way is to make T a enum of all fields and write a switch, but I it it not efficient. The faster way is to make T an offset and write
int get(Outer& o, size_t field) {
return *reinterpret_cast<int*>(reinterpret_cast<char*>(o) + field);
}
and then call it like get(o, offsetof(Outer, y) + offsetof(Inner2, c)). It works, but I am not sure if it is guaranteed to work - if it is correct to sum offsets like this and if it is safe to take member value by offset.
So, the question: is this way safe? If not, is there a safe way? Constructing values of T can be arbitrary complex, however using them should be fast.
Motivation: I will need to put values from some of nested fields in some order, known at startup, but not in compile time. I wanted to create an array of T at startup and then, when getting particular object, use this precalced array.
[UPD]: So it will be used like this:
void bar(int);
void foo(Outer& o, vector<T>& fields) {
for (auto& field : fields) {
bar(get(o, field));
}
}
You can do it this way.
/* main.cpp */
#include <string>
#include <iostream>
using namespace std;
struct Inner1 {
int a = 0, b = 0;
};
struct Inner2 {
int c = 0, d = 0;
};
struct Outer {
Inner1 x;
std::string s;
Inner2 y;
};
struct OuterMember
{
int (*getter)(Outer &obj);
};
inline int get(Outer &obj,OuterMember field) { return field.getter(obj); }
template <auto Ptr1,auto Ptr2>
auto GetInnerMember(Outer &obj) { return (obj.*Ptr1).*Ptr2; }
inline constexpr OuterMember OuterMemberA = { GetInnerMember<&Outer::x,&Inner1::a> } ;
inline constexpr OuterMember OuterMemberB = { GetInnerMember<&Outer::x,&Inner1::b> } ;
inline constexpr OuterMember OuterMemberC = { GetInnerMember<&Outer::y,&Inner2::c> } ;
inline constexpr OuterMember OuterMemberD = { GetInnerMember<&Outer::y,&Inner2::d> } ;
/* main() */
int main()
{
Outer obj;
obj.x.a=1;
obj.x.b=2;
obj.y.c=3;
obj.y.d=4;
cout << "a = " << get(obj,OuterMemberA) << endl ;
cout << "b = " << get(obj,OuterMemberB) << endl ;
cout << "c = " << get(obj,OuterMemberC) << endl ;
cout << "d = " << get(obj,OuterMemberD) << endl ;
return 0;
}
I do think this is safe (as in not a violation of strict aliasing).
However, the language does have a better mecanism for doing this: Pointers to data members, which compile down to basically an offset.
The caveat is that you'll have to make separate overloads for Inner1 and Inner2
int get(Outer& o, int Inner1::* m) {
return o.x.*m;
}
int get(Outer& o, int Inner2::* m) {
return o.y.*m;
}
int foo() {
Outer tmp;
return get(tmp, &Inner1::a) + get(tmp, &Inner2::d);
}
You can achieve the same using function template specialization see sample code below
#include <iostream>
using namespace std;
struct Inner1 {
int a = 1, b = 2;
};
struct Inner2 {
int c = 3, d = 4;
};
struct Outer {
Inner1 x;
std::string s;
Inner2 y;
};
template<typename T>
int get(Outer&o);
template<>
int get<Inner1>(Outer& o)
{
return o.x.a;
}
template<>
int get<Inner2>(Outer& o)
{
return o.y.c;
}
int main()
{
Outer out;
std::cout << get<Inner1>(out) << std::endl;
std::cout << get<Inner2>(out) << std::endl;
return 0;
}
I hope this helps!. The more interesting thing is that this is type safe.
I am trying to associate a struct's member variable with a class. So that when I create a new class, I can specify that it is associated with this member variable in a struct. For example:
struct A {
int a;
int b;
};
static A a[2];
a[0].a = 1;
a[0].b = 2;
a[1].a = 3;
a[1].b = 4;
class foo {
public:
foo(int index, ???) {
c = a[index].???; //Is it possible to define the 2nd parameter as a getter of struct A's member? So this line could resolve to either a[index].a or a[index].b?
}
private:
int c;
};
So that:
new foo(0, ???) would set c to 1 given ??? refer to A::a
new foo(0, ???) would set c to 2 given ??? refer to A::b
new foo(1, ???) would set c to 3 given ??? refer to A::a
new foo(1, ???) would set c to 4 given ??? refer to A::b
Yes, it is possible, you need to pass a data member pointer:
#include <iostream>
struct A
{
int a;
int b;
};
static A a[2]
{
1, 2
, 3, 4
};
class foo
{
public: int c;
public:
foo(int const index, int A::* const p_field)
{
c = a[index].*p_field;
}
};
int main()
{
foo const f1(0, &A::a);
::std::cout << f1.c << ::std::endl;
foo const f2(0, &A::b);
::std::cout << f2.c << ::std::endl;
foo const f3(1, &A::a);
::std::cout << f3.c << ::std::endl;
foo const f4(1, &A::b);
::std::cout << f4.c << ::std::endl;
return 0;
}
Check this code at online compiler
You have a couple options. If you just want the integer (like you have in your code you've posted), then just take an integer as a parameter to the constructor and pass it the right number.
class foo {
public:
foo(int val) {
c = val
}
private:
int c;
};
int main() {
foo f(a[0].b);
}
Or you could take a reference to an integer. This way if one changes, the other will as well:
class foo {
public:
foo(int &val) : c(val) { } //need to use an initialization list for this one
private:
int &c;
};
int main() {
foo f(a[0].b);
a[0].b = -1; //f.c will be -1 now as well
}
Using a data member pointer as in VTT's answer is the most direct solution but I often find member pointers and member function pointer syntax a bit cumbersome and I believe it is hard for the compiler to optimize.
For these kind of things I prefer to use a stateless lambda. You can pass a lambda to a function template and then the compiler can easily optimize it away:
#include <iostream>
struct A {
int a;
int b;
};
static A a[2]{{1, 2}, {3, 4}};
class foo {
public:
int c;
public:
template<typename F>
foo(int index, F getter) { c = getter(a[index]); }
};
int main() {
auto agetter = [](const A& a){ return a.a; };
auto bgetter = [](const A& a){ return a.b; };
foo const f1(0, agetter);
std::cout << f1.c << "\n";
foo const f2(0, bgetter);
std::cout << f2.c << "\n";
foo const f3(1, agetter);
std::cout << f3.c << "\n";
foo const f4(1, bgetter);
std::cout << f4.c << "\n";
}
I am writing code to access private members of a class through another friend class. The below code works
// Example program
#include <iostream>
#include <string>
using namespace std;
class Foo
{
private:
int a;
protected:
public:
friend class Bar;
Foo(int x)
{
a = x ;
}
};
class Bar
{
private:
protected:
public:
int b;
Bar(Foo& f)
{
b = f.a;
cout << "f.a is " << f.a << endl;
}
};
int main()
{
Foo foo(5);
Bar bar(foo);
cout << "Value of variable b is " << bar.b << endl;
}
Above code works fine. However, if I want to access a private variable of Foo through a function in friend class Bar, I am unable to. See code below
#include <iostream>
#include <string>
using namespace std;
class Foo
{
private:
int a;
protected:
public:
friend class Bar;
Foo(int x)
{
a = x ;
}
};
class Bar
{
private:
protected:
public:
int b;
Bar(Foo& f)
{
b = f.a;
}
void printvariable(void)
{
cout << "f.a is " << f.a << endl;
}
};
int main()
{
Foo foo(5);
Bar bar(foo);
cout << "Value of variable b is " << bar.b << endl;
}
I totally understand why execution fails on the
void printvariable(void)
{
cout << "f.a is " << f.a << endl;
}
function since f is not in scope for the function. However, since I am passing Foo f in the constructor for Bar b, I am hoping to write code that will allow me to access members in Foo without passing Foo f to the function printvariable() again.
What is the most efficient way to write this code?
You can keep the reference to f. The code should be:
class Bar
{
private:
protected:
public:
int b;
Foo& f_ref;
Bar(Foo& f)
:f_ref(f)
{
b = f.a;
}
void printvariable(void)
{
cout << "f.a is " << f_ref.a << endl;
}
};
TEST!
You can do it like this, but if I were you I'd write some getters, also – class friendship isn't really recommended.
class Bar {
public:
Foo& ref;
Bar(Foo& f)
: ref { f }
{ }
void printvariable() {
cout << "f.a is " << ref.a << endl;
}
};
Btw there's no reason to add void in brackets in C++, it lost its meaning from C and has no effect by now.
You are wrong in one point. You are indeed passing a reference to f in the ctor, but the constructor and whole class Bar does not remember a whole object of f. In your original code, the constructor only makes the Bar object remember the int a part of the object, so only that little bit is later accessible:
class Foo
{
...
friend class Bar;
...
};
class Bar
{
...
int b;
Bar(Foo& f)
{
b = f.a; // <=--- HERE
}
void printvariable(void)
{
cout << "f.a is " << b << endl; // <-- now it refers B
}
Please note how your ctor of Bar only reads f.a and stores it in b. From now on, the Bar object only remembers b and that's all. You can freely access the b in printvariable. However, it will not be the a-taken-from-f. It will be b, that was set to the same value as f.a during constructor. Since that point of time, b and f.a are totally separate. That's how value copying works.
To make Bar remember whole f, you have to, well, remember whole f:
class Bar
{
...
Foo wholeThing;
Bar(Foo& f)
{
wholeThing = f; // <=--- HERE
}
void printvariable(void)
{
cout << "f.a is " << wholeThing.a << endl;
}
However, again, there's a catch: now since wholeThing is of type Foo, the constructor will actually make a copy of that object during wholeThing=f. Just the same as it was when b=f.a, but now it remembers a copy of whole f.
Of course, it's only matter of type. You can store a reference instead of whole-Foo, but it needs a bit different initialization syntax:
class Bar
{
...
Foo& wholeThing;
Bar(Foo& f) :
wholeThing(f) // <=--- HERE
{
// <=--- empty
}
void printvariable(void)
{
cout << "f.a is " << wholeThing.a << endl;
}
I have a templated class pair, and I'd like to write a show function outside of the class to do some fancy couting. When specifying the template type in show explictly, it all works as expected:
#include <iostream>
template <class A_Type>
class pair
{
public:
A_Type a0;
A_Type a1;
};
void show(const pair<double> & p) {
std::cout << p.a0 << std::endl;
std::cout << p.a1 << std::endl;
}
int main() {
pair<double> p;
p.a0 = 1.2;
p.a1 = 1.3;
show(p);
}
I'd like to have show oblivious of the template type though.
Any hints?
You can change show function to:
template<typename DataType>
void show(const pair<DataType> & p) {
std::cout << p.a0 << std::endl;
std::cout << p.a1 << std::endl;
}
Or a better approach (in my opinion) is to make show function member of the class:
template <class A_Type>
class pair {
public:
A_Type a0;
A_Type a1;
void show() const {
std::cout << this->a0 << std::endl;
std::cout << this->a1 << std::endl;
}
};
and then simply:
int main() {
pair<double> p;
p.a0 = 1.2;
p.a1 = 1.3;
p.show();
}
I want to achieve something similar in c++. This here is a c# code. I want to avoid raw pointers as much as possible.
class Program
{
public class Foo
{
public int v1;
public int v2;
public Foo(int a, int b)
{
v1 =a; v2 =b;
}
};
public class Bar
{
public static void getFoo(out Foo fooObj)
{
fooObj = new Foo(1,2);
}
};
static void Main()
{
Foo fooObj = null;
Bar.getFoo(out fooObj);
Console.WriteLine("Foo.v1="+fooObj.v1);
Console.WriteLine("Foo.v2="+fooObj.v2);
}
}
Here goes my attempt to convert your C# code into C++. However, once you run it you need to do proper research on how to use use all the features I've used here. unique_ptr will basically manage the "raw" pointer for you (which is what you want, and it will free it once it goes out of scope). I've added an improved version using variadic templates so you can pass any number of arguments of any type to dynamically create your Foo class.
#include <memory>
#include <iostream>
class Foo
{
public:
int v1;
int v2;
Foo(int a, int b)
{
v1 =a; v2 =b;
}
};
class Bar
{
public:
// This is what your function looks like in C++
static void getFoo(std::unique_ptr<Foo>& fooObj)
{
fooObj = std::make_unique<Foo>(1, 2);
}
// This is a better implementation.
template<typename ...Args>
static void getFoo_improved(std::unique_ptr<Foo>& fooObj, Args&&... args)
{
fooObj = std::make_unique<Foo>(std::forward<Args>(args)...);
}
// This is the one used more often in C++ tho.
template<typename ...Args>
static std::unique_ptr<Foo> getFoo_improved_x2(Args&&... args)
{
return std::make_unique<Foo>(std::forward<Args>(args)...);
}
};
int main()
{
std::unique_ptr<Foo> fooObj = nullptr; //nullptr is not needed tho
Bar::getFoo(fooObj);
std::unique_ptr<Foo> fooObj_alt = nullptr; //nullptr is not needed tho
Bar::getFoo_improved(fooObj_alt, 9, 10);
//This is as fast as the other two
auto fooObj_alt_x2 = Bar::getFoo_improved_x2(50, 60);
std::cout << "Foo.v1=" << fooObj->v1 << std::endl;
std::cout << "Foo.v2=" << fooObj->v2 << std::endl;
std::cout << "Foo_alt.v1=" << fooObj_alt->v1 << std::endl;
std::cout << "Foo_alt.v2=" << fooObj_alt->v2 << std::endl;
std::cout << "Foo_alt_x2.v1=" << fooObj_alt_x2->v1 << std::endl;
std::cout << "Foo_alt_x2.v2=" << fooObj_alt_x2->v2 << std::endl;
return 0;
}