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 » Community » U++ community news and announcements » get_i
Re: get_i [message #54273 is a reply to message #54272] Wed, 17 June 2020 21:03 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 12581
Registered: November 2005
Ultimate Member
Novo wrote on Wed, 17 June 2020 19:14
Another fix to avoid extra-copying ...
	template <class I, class V>
	void iter_set(I& t, V&& v)
	{
		*t = std::forward<V>(v);
	}
	
	template <class I, class V, typename... Args>
	void iter_set(I& t, V&& v, Args&& ...args)
	{
		*t++ = std::forward<V>(v);
		iter_set(t, std::forward<Args>(args)...);
	}
	
	template <class C, typename... Args>
	C gather(Args&& ...args)
	{
		C x;
		x.SetCount(sizeof...(args));
		auto iter = x.Begin();
		iter_set(iter, std::forward<Args>(args)...);
		return x;
	}


Thanks. Trunk version are a bit different now, can you review?
Re: get_i [message #54274 is a reply to message #54273] Wed, 17 June 2020 23:21 Go to previous messageGo to next message
Novo is currently offline  Novo
Messages: 1048
Registered: December 2006
Experienced Contributor
mirek wrote on Wed, 17 June 2020 15:03

Thanks. Trunk version are a bit different now, can you review?

In your last commit you've added std::forward not to all places.
I've attached my version.
I also changed a functor signature in "void iter_get(I s, Args& ...args)".
Just a reference is fine there ...
IMHO, functors and iterators should be passed by reference to avoid extra-copying ...
  • Attachment: Fn.h
    (Size: 3.28KB, Downloaded 9 times)


Regards,
Novo
Re: get_i [message #54275 is a reply to message #54274] Wed, 17 June 2020 23:59 Go to previous messageGo to next message
Novo is currently offline  Novo
Messages: 1048
Registered: December 2006
Experienced Contributor
A more generic version of
template <typename... T>
constexpr const char *get_i(int i, const char* p0, const T& ...args)
{
	const char *list[] = { p0, args... };
	return list[clamp(i, 0, (int)sizeof...(args))];
}

	template <typename A, typename... T>
	constexpr A* get_i(int i, A* p0, const T& ...args)
	{
		A* list[] = { p0, args... };
		return list[clamp(i, 0, (int)sizeof...(args))];
	}

Example:
	const char* cr = get_i(1, "0", "11", "222");
	RLOG(cr);
	cr = get_i(1, "0", String("11"), "222");
	RLOG(cr);
	const wchar _0[] = {0};
	const wchar _3[] = {2, 2, 2};
	const wchar* wcr = get_i(1, _0, WString("11"), _3);
	RLOG(wcr);


Regards,
Novo

[Updated on: Thu, 18 June 2020 00:00]

Report message to a moderator

Re: get_i [message #54279 is a reply to message #54275] Thu, 18 June 2020 08:39 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 12581
Registered: November 2005
Ultimate Member
Thanks, applied...

Mirek
Re: get_i [message #54282 is a reply to message #54279] Thu, 18 June 2020 23:56 Go to previous messageGo to next message
Novo is currently offline  Novo
Messages: 1048
Registered: December 2006
Experienced Contributor
mirek wrote on Thu, 18 June 2020 02:39
Thanks, applied...

Mirek

No problem.
There is still a bug with
template <typename P, typename... T>
constexpr const P *get_i(int i, const P* p0, const T& ...args)
{
	const char *list[] = { p0, args... };
	return list[clamp(i, 0, (int)sizeof...(args))];
}

It has to look like below.
template <typename P, typename... T>
constexpr const P *get_i(int i, const P* p0, const T& ...args)
{
	const P *list[] = { p0, args... };
	return list[clamp(i, 0, (int)sizeof...(args))];
}


Regards,
Novo
Re: get_i [message #54348 is a reply to message #54247] Mon, 29 June 2020 19:23 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 12581
Registered: November 2005
Ultimate Member
I have just found that this fails with Visual C++ compiler:

	String n = " 2";
	ASSERT(decode(4, 1, "one", 2, "two", 3, "three", "unknown" + n) == String("unknown 2"));


The problem is that temporaty object gets destroyed too early...

I _believe_ this is a compiler error. In any case, it is pretty bad.

EDIT: Not a compiler bug. The problem is in your decode. Fixed it with

template <class T, class V>
constexpr const V& decode(const T& sel, const V& def)
{
	return def;
}

template <class T, class K, class V, typename... L>
constexpr const V& decode(const T& sel, const K& k, const V& v, const L& ...args)
{
	return sel == k ? v : decode(sel, args...);
}

template <class T>
constexpr const char *decode(const T& sel, const char *def)
{
	return def;
}

template <class T, class K, typename... L>
constexpr const char *decode(const T& sel, const K& k, const char *v, const L& ...args)
{
	return sel == k ? v : (const char *)decode(sel, args...);
}

[Updated on: Mon, 29 June 2020 23:08]

Report message to a moderator

Re: get_i [message #54350 is a reply to message #54247] Thu, 02 July 2020 22:08 Go to previous messageGo to next message
Novo is currently offline  Novo
Messages: 1048
Registered: December 2006
Experienced Contributor
Sorry for the late response.
My code is correct. Temporary String lives only during function call. This is how C++ works.
Return type is a value, not a reference. So, no temporaries ...

"The type of the ternary ?: expression is the common type of its second and third argument. If both types are the same, you get a reference back. If they are convertable to each other, one gets chosen and the other gets converted (promoted in this case). Since you can't return an lvalue reference to a temporary (the converted / promoted variable), its type is a value type."

Basically, the ternary ?: is needed to convert "const char[N]" and "const char[M]" to "const char*".

On the other side, templates is a complicated thing.
If you have a non-template version of "decode" declared before template instantiation point, compiler will choose it ...
Also MSVC is very well known for broken "two-phase name lookup". Even till these days, I believe ...
IMHO, a safer version would look like this:
namespace details {
	template <class T, class V>
	constexpr auto decode(const T& sel, const V& def)
	{
		return def;
	}
	
	template <class T, class K, class V, typename... L>
	constexpr auto decode(const T& sel, const K& k, const V& v, const L& ...args)
	{
		return sel == k ? v : details::decode(sel, args...);
	}
}
	
template <class T, class K, class V, typename... L>
constexpr auto decode(const T& sel, const K& k, const V& v, const L& ...args)
{
	return details::decode(sel, k, v, args...);
}


Regards,
Novo
Re: get_i [message #54353 is a reply to message #54350] Fri, 03 July 2020 09:38 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 12581
Registered: November 2005
Ultimate Member
Novo wrote on Thu, 02 July 2020 22:08
Sorry for the late response.
My code is correct. Temporary String lives only during function call. This is how C++ works.


I would not be fixing if it was correct. Whole thing was actual error in actual application.

Indeed, temp string lives only during function call. What happened here is that in some circustances when mixing String and const char * parameters, const char * gets converted to String temporary, then back to const char *, then temporary is detroyed and dangling const char * returned.

Quote:

Return type is a value, not a reference. So, no temporaries ...

And that is exactly the problem. That return value is temporary one level up and gets converted to const char *....

It is very tricky indeed. Actually the version posted here was not final, it needed more fixes for other situations (namely enums). Hopefully trunk version is now ok. Full test is in "autotest/decode". Also the error only appears with MSC, but I have checked, the problem is not in the compiler.

[Updated on: Fri, 03 July 2020 10:10]

Report message to a moderator

Re: get_i [message #54362 is a reply to message #54353] Fri, 03 July 2020 18:53 Go to previous messageGo to next message
Novo is currently offline  Novo
Messages: 1048
Registered: December 2006
Experienced Contributor
I guess that the problem is that in case of MSVC common type of const char* and String is const char*, and in case of Clang it is String.

Regards,
Novo
Re: get_i [message #54363 is a reply to message #54362] Fri, 03 July 2020 19:03 Go to previous message
mirek is currently offline  mirek
Messages: 12581
Registered: November 2005
Ultimate Member
Novo wrote on Fri, 03 July 2020 18:53
I guess that the problem is that in case of MSVC common type of const char* and String is const char*, and in case of Clang it is String.


Yes, however that does not break C++ specification... BTW, I had to do another fix today... Smile Converting decode to vararg templates is really pandora's box...
Previous Topic: SIMD encapsulation
Next Topic: 2020.1 officially released
Goto Forum:
  


Current Time: Wed Jul 15 03:14:11 CEST 2020

Total time taken to generate the page: 0.00979 seconds