Long time no see and Input Capture

The Partridge Family were neither partridges nor a family. Discuss.
cameron
Posts: 794
Joined: June 26th, 2012, 5:38 pm
Location: USA

Re: Long time no see and Input Capture

Post by cameron » November 23rd, 2018, 9:00 am

Yeah, sorry forgot to paste the updated code for that. Also there was a contributing error because of explicitly passing the Args... to MakeFunc. With perfect forwarding, explicitly specifying the types messes things up.

Anyways... Im pretty sure I got that mostly working. Trying out a FunctionAny class with std::variant now. Not sure exactly how useful it will be as you generally need to know the parameters and return type to make use of it (stored in a vector/list). It could be nice for different return types but you could get around that anyways by making a wrapper. But the main reason for doing this was to fool around some more with the variant system you used for InputData.

Im getting close I think but having a few issues. Made a separate git repo for ease of testing https://github.com/BobsCrabShack/FunctionAny_Test

The only issue right now is with FunctionAny::operator()
Computer too slow? Consider running a VM on your toaster.

cameron
Posts: 794
Joined: June 26th, 2012, 5:38 pm
Location: USA

Re: Long time no see and Input Capture

Post by cameron » November 24th, 2018, 12:37 am

Looks like I finally got something working. However, I'm not able to get different return types working because std::visit requires a single return type.

Side note: templates are fun but this is literally templated hell. I had to create a FunctionTraits header just because of the dummy structs I've had to make to get this working.
Computer too slow? Consider running a VM on your toaster.

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Long time no see and Input Capture

Post by albinopapa » November 24th, 2018, 12:52 am

Yeah, creating some sort of type trait library is the only way to keep things organized.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Long time no see and Input Capture

Post by albinopapa » November 24th, 2018, 1:00 am

Chili had suggested returning an std::any, but not sure how you'd get the type info back. As far I know there isn't a visitor pattern for std::any.

One thing you might try, is having the std::visit function return another std::variant of all the return types you are expecting, at least that way std::visit would be returning the same type.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

cameron
Posts: 794
Joined: June 26th, 2012, 5:38 pm
Location: USA

Re: Long time no see and Input Capture

Post by cameron » November 24th, 2018, 8:10 pm

Yeah std::any is gonna lose any type information with it though its not a terrible solution I suppose.
Been trying to return an std::variant with all the return types. I mostly have it working but I cant seem to get the void type working. I created a dummy VOID struct but it's having conversion errors for some reason.

The error is given on these statements:

Code: Select all

return RTs( VOID{} );
Computer too slow? Consider running a VM on your toaster.

cameron
Posts: 794
Joined: June 26th, 2012, 5:38 pm
Location: USA

Re: Long time no see and Input Capture

Post by cameron » November 24th, 2018, 10:15 pm

Ok... I have it mostly working (LOL). It now works for all non-reference return types. Turns out it was an issue with duplicates in the variadic template. Had to put together another hack to remove the duplicates. This is really turning out to be template city.

On the other hand, this is quite sexy, if I do say so myself.

I have it working so that you can "attempt" to invoke any function with a set of parameters. Basically, it does a compile-time check to see if one argument list is convertible to another and calls it if it is and returns NO_CALL{} otherwise.
If the argument list is not convertible to the signature (arguments only) of the stored function it returns NO_CALL{};

Now I can do something of the likes of:

Code: Select all

	auto rt_visitor = [](const auto& ret)
	{
		using RT = std::decay_t<decltype(ret)>;
		if constexpr (std::is_same_v<RT, VOID>)
		{
			//std::cout << "Func returned with type: void" << std::endl;
		}
		else if constexpr (std::is_same_v<RT, NO_CALL>)
		{
			//std::cout << "Func was not called" << std::endl;
		}
		else if constexpr (std::is_same_v<RT, int>)
		{
			std::cout << "Func returned " << ret << " with type: int" << std::endl;
		}
		else if constexpr (std::is_same_v<RT, std::string>)
		{
			std::cout << "Func returned " << ret << " with type: string" << std::endl;
		}
		else if constexpr (std::is_same_v<RT, A>)
		{
			std::cout << "Func returned {" << static_cast<A>(ret).m_i << ", " << static_cast<A>(ret).m_f << "} with type: A" << std::endl;
		}
		else if constexpr (std::is_same_v<RT, A*>)
		{
			std::cout << "Func returned " << ret << " {" << static_cast<A*>(ret)->m_i << ", " << static_cast<A*>(ret)->m_f << "} with type: A*" << std::endl;
		}
		else
		{
			std::cout << "Invalid Return type" << std::endl;
		}
	};

	for (auto& it : funcList)
	{
		it.Invoke(rt_visitor);
		it.Invoke(rt_visitor, a, 5.0, 6);
		it.Invoke(rt_visitor, std::ref(a));
	}
Im sure this aint cheap to call.
Considering it requires 1/2 (2 if need the return type back) calls to std::visit and does lots of forwarding of parameters to different functions. The good news is most of nitty gritty stuff is hidden away from the user, so the class is fairly easy to use. Maybe I'll find a use for it eventually... lol. RIght now it's more of a science project. I'm still surprised I ended up getting this to work.

-edit:
Made it so return value references are automatically converted to pointer type.
Computer too slow? Consider running a VM on your toaster.

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Long time no see and Input Capture

Post by albinopapa » November 25th, 2018, 10:51 pm

Not sure about the forwarding stuff, some of it should be elided by the compiler due to inlining possibly. The only bottleneck I can see would be the use of std::function, though I don't know what the cost of it is to be honest. I've just seen videos where people have said std::function is comparatively slow to lambdas or other function objects and of course, plain function pointers.

Still, good job. I would use something like this for callback or delegate behavior, hooks and the like. Instead of an Observer/Subject, you could just use one of these classes to pass handlers for different events. Each event could have a vector of these function wrappers, or something along those lines.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

Post Reply