how to implement a class that support both default ctor and operator=

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>
#include <string>
using namespace std;

struct create_info {
	string text;
};

struct window {
	create_info c_info;

	window() {}
};

template<typename wnd_t>
struct wnd {
	wnd_t* impl;

	wnd() {
		impl = new wnd_t;
	}
	wnd(create_info& ci) { // plan 1
		impl->c_info = ci;
	}
};

int main() {
	// usage 1
	wnd<window> w1; 
	w1 = create_info(); // need to support this
	cout << w1.impl->c_info.text << endl;
	// usage 2
	wnd<window> w2 = create_info();// also need to support this
	cout << w2.impl->c_info.text << endl;
}

I need the wnd class support both usage 1/2, but the code crashes. From the debugger I see this line
w1 = create_info();
creates a new instance of wnd, and in the constructor impl is used without being initialized.
Anyway to solve this?

Thanks.

Last edited on
well, since impl is not initialized, do initialize it before attempting impl->c_info

While you're at it, you could change its type to a better-behaved pointer, since otherwise you have more code to write (destructor, copy ctor, copy assignment at least)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <string>
#include <memory>
using namespace std;

struct create_info {
    string text;
    create_info() : text("just testing") {}
};

struct window {
    create_info c_info;

    window() {}
};

template<typename wnd_t>
struct wnd {
    std::unique_ptr<wnd_t> impl; // before C++11, use std::auto_ptr

    wnd() : impl(new wnd_t) {
    }

    wnd(const create_info& ci) : impl(new wnd_t)  {   
        impl->c_info = ci;
    }
};

int main() {
    wnd<window> w1;

    w1 = create_info();
    cout << w1.impl->c_info.text << '\n';

    wnd<window> w2 = create_info();
    cout << w2.impl->c_info.text << '\n';
}
Last edited on
Thanks,
but here's another problem that i forgot to say in the first post, three windows are created

1
2
3
4
5
6
7
struct window {
	create_info c_info;

	window() {
		cout << "window instance creating" << endl;//this displays three times
	}
};

so I didn't initialize impl in the second constructor.
Last edited on
That's because w2 = create_info(); creates and destroys a temporary in this case. You could add an assignment operator that takes a create_info on the right, if you need to avoid that temporary:

1
2
3
4
5
   wnd& operator=(const create_info& ci) {
        impl->c_info = ci;
        return *this;
    }
};

Although this is questionable usage: I would make the constructor from create_info explicit and disallow assignment from create_info altogether. Do you have a use for a default-constructed wnd?
Last edited on
At first I thought the wnd should have default create_info even if not explicitly constructed with a create_info, maybe it's not necessary:)
anyway the operator=() works fine

Thanks Cubbi.
Topic archived. No new replies allowed.