Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
Bazaar
Status & Roadmap
FAQ
Authors & License
Forums
Funding Ultimate++
Search on this site
Search in forums












SourceForge.net Logo
Home » U++ Library support » U++ Core » Fixes to Array::Create & Vector::Create
Fixes to Array::Create & Vector::Create [message #49076] Fri, 15 December 2017 03:46 Go to next message
Novo is currently offline  Novo
Messages: 1358
Registered: December 2006
Ultimate Contributor
Hi Mirek,

Could you please change methods Array::Create & Vector::Create to make them look like below?
	template<class TT, class... Args>
	TT& Create(Args&&... args)          { TT *q = new TT(pick(args)...); Add(q); return *q; }

	template <class... Args>
	T&       Create(Args&&... args)    { if(items >= alloc) GrowF(); return *(::new(Rdd()) T(pick(args)...)); }

This shouldn't break anything, and as a bonus this should allow to pass arguments by reference in case they do not have a copy constructor, what is quite common with Upp.

Regards,


Regards,
Novo
Re: Fixes to Array::Create & Vector::Create [message #49077 is a reply to message #49076] Fri, 15 December 2017 09:10 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Novo wrote on Fri, 15 December 2017 03:46
Hi Mirek,

Could you please change methods Array::Create & Vector::Create to make them look like below?
	template<class TT, class... Args>
	TT& Create(Args&&... args)          { TT *q = new TT(pick(args)...); Add(q); return *q; }

	template <class... Args>
	T&       Create(Args&&... args)    { if(items >= alloc) GrowF(); return *(::new(Rdd()) T(pick(args)...)); }

This shouldn't break anything, and as a bonus this should allow to pass arguments by reference in case they do not have a copy constructor, what is quite common with Upp.

Regards,


Just changing them to r-value would potentially break a lot. However, I am trying to add them as overload.
Re: Fixes to Array::Create & Vector::Create [message #49078 is a reply to message #49077] Fri, 15 December 2017 09:28 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
	template <class... Args>
	T&       Create(const Args&... args) { if(items >= alloc) GrowF(); return *(::new(Rdd()) T(args...)); }
	template <class... Args>
	T&       Create(Args&&... args)  { if(items >= alloc) GrowF(); return *(::new(Rdd()) T(pick(args)...)); }

Re: Fixes to Array::Create & Vector::Create [message #49079 is a reply to message #49078] Fri, 15 December 2017 09:44 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Unfortunately, this seems not to work:

struct Test {
	Vector<int> a;
	int         b;
	
	Test(Vector<int>&& a, int b) : a(pick(a)), b(b) {}
};

CONSOLE_APP_MAIN
{
	Array<Test> h;
	Vector<int> v;
	v.Add(12);
	h.Create<Test>(v, 22);
	DDUMP(v.GetCount());
	h.Create<Test>(pick(v), 22);
	DDUMP(v.GetCount());
}


Here, I would expect const Args& for the first 'Create' and && for the second one.

For some reason, both end in && overload (I am really not sure why, IMO they should not, but they do with both MSC and GCC).

So unfortunately, to stay safe, I am going to rollback this feature. This has really trivial workaround (default constructor + Set method).

Mirek
Re: Fixes to Array::Create & Vector::Create [message #49083 is a reply to message #49079] Fri, 15 December 2017 17:40 Go to previous messageGo to next message
Novo is currently offline  Novo
Messages: 1358
Registered: December 2006
Ultimate Contributor
Sorry, my bad. The code should look like below.

	
	template<class TT, class... Args>
	TT& Create(Args&&... args)          { TT *q = new TT(std::forward<Args>(args)...); Add(q); return *q; }

struct Test {
	Test(const Vector<int>& a, int b) : a(a, 0), b(b) {}
	Test(Vector<int>&& a, int b) : a(pick(a)), b(b) {}
	
	Vector<int> a;
	int         b;
};

CONSOLE_APP_MAIN
{
	Array<Test> h;
	Vector<int> v;
	v.Add(12);
	// Copy-constructor
	h.Create<Test>(v, 22);
	DDUMP(v.GetCount());
	// Move-constructor
	h.Create<Test>(pick(v), 22);
	DDUMP(v.GetCount());
	v.Add(21);
	h.Create<Test>(Vector<int>(v, 0), 22);
	DDUMP(v.GetCount());
}


I recompiled TheIDE with this change and it works perfectly for me.

How it works.
type&& is called a universal/perfect/forwarding reference and it can be ether type&& or type& depending on arguments. This is why your method Create(const Args&... args) was redundant. Create(Args&&... args) is a better match.
The problem was that I was using pick, which unconditionally converts type to an rvalue, instead of std::forward, which preservers type (an lvalue will stay the lvalue).


Regards,
Novo

[Updated on: Fri, 15 December 2017 18:21]

Report message to a moderator

Re: Fixes to Array::Create & Vector::Create [message #49085 is a reply to message #49083] Sat, 16 December 2017 09:24 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Perfect, applied.

Now I have just to add this to all Create methods everywhere Smile (not only Array/Vector)
Re: Fixes to Array::Create & Vector::Create [message #49090 is a reply to message #49076] Sat, 16 December 2017 21:02 Go to previous message
Novo is currently offline  Novo
Messages: 1358
Registered: December 2006
Ultimate Contributor
Thanks a lot!

Regards,
Novo
Previous Topic: Performance problem with XmlParser::Next()
Next Topic: how to use xmlparser to parse this document?
Goto Forum:
  


Current Time: Thu Mar 28 14:30:36 CET 2024

Total time taken to generate the page: 0.00879 seconds