cs_signal icon indicating copy to clipboard operation
cs_signal copied to clipboard

Cannot create connection to function with different exception specifier

Open jvoosten opened this issue 2 years ago • 2 comments

The following will not compile due to the 'noexcept' specifier on the activate() function:

class Receiver: public CsSignal::SlotBase
{
public:
  Receiver ();
  void activate () noexcept;
};

class Sender: public CsSignal::SignalBase
{
public:
  Sender ();

  SIGNAL_1 (void send ());
  SIGNAL_2 (send);
};

int main(int argc, char *argv[])
{
  Sender transmitter;
  Receiver radio;

  connect (transmitter, &Sender::send, radio, &Receiver::activate);

  return 0;
}

with the following error:

cs_internal.h(432): error C2825: 'T': must be a class or namespace when followed by '::'
cs_signal.h(341): note: see reference to class template instantiation 'CsSignal::Internal::Bento<void (__cdecl Receiver::* )(void) noexcept>' being compiled
main.cpp(12): note: see reference to function template instantiation 'bool CsSignal::connect<Sender,Sender,,Receiver,void(__cdecl Receiver::* )(void) noexcept>(const Sender &,void (__cdecl Sender::* )(void),const Receiver &,T,CsSignal::ConnectionKind,bool)' being compiled
          with
          [
              Sender=Sender,
              Receiver=Receiver,
              T=void (__cdecl Receiver::* )(void) noexcept
          ]
cs_internal.h(432): error C2653: 'T': is not a class or namespace name
cs_internal.h(432): error C2269: cannot create a pointer or reference to a qualified function type (requires pointer-to-member)
cs_internal.h(435): error C2825: 'T': must be a class or namespace when followed by '::'
cs_internal.h(435): error C2653: 'T': is not a class or namespace name
cs_internal.h(435): error C2535: 'void CsSignal::Internal::Bento<void (__cdecl Receiver::* )(void) noexcept>::invoke_internal(const CsSignal::Internal::TeaCupAbstract *,MethodReturn (__cdecl *)(MethodArgs...)) const': member function already defined or declared
cs_internal.h(432): note: see declaration of 'CsSignal::Internal::Bento<void (__cdecl Receiver::* )(void) noexcept>::invoke_internal'

This is with CsSignal 1.2.3 and Visual Studio CE 2022.

Making the send() function noexcept does not help.

I am not sure if there is an easy solution. The 'noexcept' specification is part of the function type but I don't know if it is used for scope resolution (e.g. matching function type to function by the compiler, like const vs. non-const). Adding a copy of invoke_internal() with a noexcept specifier did not help...

jvoosten avatar Dec 07 '22 02:12 jvoosten

It appears that the 'noexcept' is being deduced as part of the data type passed into CsSignal::Internal::Bento, which results in an instantiation of a template which does not exist. As a possible workaround, I would try casting the slot method pointer to remove the noexcept specifier in your call to connect:

connect (transmitter, &Sender::send, radio, static_cast<void (Receiver::*)()>(&Receiver::activate));

Will this work for your use case?

We have added a task on our roadmap to look at a more general solution.

agserm avatar Dec 13 '22 03:12 agserm

For now that is an acceptable workaround. Thank you for looking into this.

jvoosten avatar Dec 16 '22 11:12 jvoosten