Iam new in C++ and do not know what am I doing so please help. The issue is, when Iam trying to do this in Visual Studio 2022, it does not compile:
I replaced std::function with this in my codebase. It supposed to be used as a delegate in event system.
TFunction.h:
namespace t3d
{
template<typename T> class TFunction;
template<typename Return_T, typename... Args_T>
class TFunction<Return_T(Args_T...)>
{
public:
// Aliases:
template<class C>
using CallbackMember_T = Return_T(C::*)(Args_T...);
using CallbackStatic_T = Return_T(*)(Args_T...);
// Constructors:
TFunction()
: CallbackMember (nullptr)
, FunctionPointers { &TFunction::CallMember, &TFunction::CallStatic }
, CallbackStatic (nullptr)
, Instance (nullptr)
, Index (0)
{
}
template<class C>
TFunction(C* Instance, CallbackMember_T<C> Callback)
: CallbackMember (reinterpret_cast<CallbackMember_T<FInstance>>(Callback))
, FunctionPointers { &TFunction::CallMember, &TFunction::CallStatic }
, CallbackStatic (nullptr)
, Instance (reinterpret_cast<FInstance*>(Instance))
, Index (0)
{
}
TFunction(CallbackStatic_T Callback)
: CallbackMember (nullptr)
, FunctionPointers { &TFunction::CallMember , &TFunction::CallStatic }
, CallbackStatic (Callback)
, Instance (nullptr)
, Index (1)
{
}
// Functions:
template<class C>
constexpr void Bind(C* Instance, CallbackMember_T<C> Callback) noexcept
{
this->Instance = reinterpret_cast<FInstance*>(Instance);
this->CallbackMember = reinterpret_cast<CallbackMember_T<FInstance>>(Callback);
this->CallbackStatic = nullptr;
this->Index = 0;
}
constexpr void Bind(CallbackStatic_T Callback) noexcept
{
this->Instance = nullptr;
this->CallbackMember = nullptr;
this->CallbackStatic = Callback;
this->Index = 1;
}
constexpr Return_T Invoke(Args_T... Args) const
{
return (this->*FunctionPointers[Index])(std::forward<Args_T>(Args)...);
}
template<class C>
constexpr bool8 IsEqual(CallbackMember_T<C> Callback) const
{
return reinterpret_cast<CallbackMember_T<C>>(CallbackMember) == Callback;
}
constexpr bool8 IsEqual(CallbackStatic_T Callback) const noexcept
{
return CallbackStatic == Callback;
}
constexpr bool8 IsEmpty() const noexcept
{
return (Instance == nullptr) && (CallbackMember == nullptr) && (CallbackStatic == nullptr);
}
// Operators:
explicit operator bool () const noexcept
{
return (Instance && CallbackMember) || CallbackStatic;
}
constexpr bool8 operator == (const TFunction& Right) const noexcept
{
return (Instance == Right.Instance) && (CallbackMember == Right.CallbackMember) && (CallbackStatic == Right.CallbackStatic);
}
constexpr bool8 operator != (const TFunction& Right) const noexcept
{
return (Instance != Right.Instance) || (CallbackMember != Right.CallbackMember) || (CallbackStatic != Right.CallbackStatic);
}
private:
using CallbackInternal_T = Return_T(TFunction::*)(Args_T...) const;
// Private Functions:
Return_T CallMember(Args_T... Args) const
{
return (Instance->*CallbackMember)(std::forward<Args_T>(Args)...);
}
Return_T CallStatic(Args_T... Args) const
{
return (*CallbackStatic)(std::forward<Args_T>(Args)...);
}
// Variables:
class FInstance {};
CallbackMember_T<FInstance> CallbackMember;
CallbackInternal_T FunctionPointers[2];
CallbackStatic_T CallbackStatic;
FInstance* Instance;
uint64 Index;
};
}
Main.cpp:
Here am I testing TFunction with this exact code:
struct FData
{
int A;
int B;
};
struct FResult
{
bool Success;
};
class FBase1
{
public:
virtual FResult Function1(FData Data)
{
return FResult{ true };
}
};
class FBase2
{
public:
virtual FResult Function2(FData Data)
{
return FResult{ true };
}
};
class FDerived : public FBase1, public FBase2
{
public:
FResult Function1(FData Data) override
{
return FResult{ true };
}
FResult Function2(FData Data) override
{
return FResult{ true };
}
FResult Function3(FData Data)
{
return FResult{ true };
}
};
FResult FunctionGlobal(FData Data)
{
return FResult{ true };
}
t3d::int32 main()
{
FDerived Derived;
t3d::TFunction<FResult(FData)> TestFunction;
TestFunction.Bind(&Derived, &FDerived::Function1); // Error C2440
TestFunction.Bind(&Derived, &FDerived::Function2); // Error C2440
TestFunction.Bind(&Derived, &FDerived::Function3); // Error C2440
return 0;
}
Error says: 'reinterpret_cast': cannot convert from 'Return_T (__cdecl FDerived::* )(FData)' to 'Return_T (__cdecl t3d::TFunction<FResult (FData)>::FInstance::* )(FData)'
Any ideas?
Edited: Binding works fine with nested inheritance or with no inheritance, but not with inheritance from multiple classes.