Advertisement

opImplConv to bool doesn't work in a ternary operator condition

Started by October 01, 2022 03:10 PM
9 comments, last by Solokiller 2 years, 1 month ago

When using opImplConv to bool and then checking an instance of the type in a ternary operator condition a compiler error is given:

Expression must be of boolean type

It does work when used in an if statement, so this seems like an oversight.

Registration code:

class Scheduler
{
public:
	struct ScheduledFunction {};

	struct ScheduledFunctionHandle
	{
		ScheduledFunction* Function{};
		std::chrono::system_clock::time_point CreationTime{};
	};
};

static void ConstructScheduledFunctionHandle(void* memory)
{
	new (memory) Scheduler::ScheduledFunctionHandle();
}

static void DestructScheduledFunctionHandle(Scheduler::ScheduledFunctionHandle* handle)
{
	handle->~ScheduledFunctionHandle();
}

static void CopyConstructScheduledFunctionHandle(void* memory, const Scheduler::ScheduledFunctionHandle& other)
{
	new (memory) Scheduler::ScheduledFunctionHandle(other);
}

static bool ScheduledFunction_opImplConv(const Scheduler::ScheduledFunctionHandle* handle)
{
	return handle->Function != nullptr;
}

static void RegisterScheduledFunction(asIScriptEngine& engine)
{
	const char* const name = "ScheduledFunction";

	engine.RegisterObjectType(name, sizeof(Scheduler::ScheduledFunctionHandle), asOBJ_VALUE | asGetTypeTraits<Scheduler::ScheduledFunctionHandle>());

	engine.RegisterObjectBehaviour(name, asBEHAVE_CONSTRUCT, "void f()",
		asFUNCTION(ConstructScheduledFunctionHandle), asCALL_CDECL_OBJFIRST);

	engine.RegisterObjectBehaviour(name, asBEHAVE_DESTRUCT, "void f()",
		asFUNCTION(DestructScheduledFunctionHandle), asCALL_CDECL_OBJFIRST);

	engine.RegisterObjectBehaviour(name, asBEHAVE_CONSTRUCT, "void f(const ScheduledFunction& in other)",
		asFUNCTION(CopyConstructScheduledFunctionHandle), asCALL_CDECL_OBJFIRST);

	engine.RegisterObjectMethod(name, "ScheduledFunction& opAssign(const ScheduledFunction& in other)",
		asMETHODPR(Scheduler::ScheduledFunctionHandle, operator=, (const Scheduler::ScheduledFunctionHandle&), Scheduler::ScheduledFunctionHandle&),
		asCALL_THISCALL);

	engine.RegisterObjectMethod(name, "bool opImplConv() const",
		asFUNCTION(ScheduledFunction_opImplConv), asCALL_CDECL_OBJFIRST);
}

Script code:

ScheduledFunction sched;
Print("Scheduled function handle is valid: " + sched ? "yes" : "no" + "\n");

Thanks for reporting this. I'll look into this.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Advertisement

Uhm…

Have you tried adding parenthesis in that expression? ?

Print("Scheduled function handle is valid: " + (sched ? "yes" : "no") + "\n");

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

That does work. Sorry about that, the error message seemed to indicate that it was the implicit conversion that wasn't working. Looks like it's implicitly converting the value type to bool, calling opAdd and then trying to evaluate the result? Allowing implicit operator+ with bool seems like it could cause problems, i'd use an explicit conversion like C++'s to_string overloads.

Allowing the implicit conversion to bool in conditions but not in other operations is currently not possible. In this case it is probably best not to implement the opImplConv to bool at all.

Anyway, yesterday I improved the error message in rev 2796 to include the type of the expression that is used for the condition. It would probably have helped you understand better where the problem was:

Expression must be of boolean type, instead found 'string'

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Advertisement

I meant that it should not be possible to do this:

string str = "this is a string: " + true;

The default string addon allows this, but i'm suggesting it should require this:

string str = "this is a string: " + to_string(true);

I'll think about it, perhaps I'll add a compile time macro to skip the registration of the operator on the string add-on. But for now you can just update the add-on yourself.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Alright, thanks. It would be great if such a macro could disable all implicit conversions (i.e. only other strings can be used with the string API) to harden against accidental conversions.

I've added this in revision 2798.

Regards,
Andreas

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

This topic is closed to new replies.

Advertisement