diff --git a/nestkernel/connection.h b/nestkernel/connection.h index 5ec146c963f..45cbc7a8d7d 100644 --- a/nestkernel/connection.h +++ b/nestkernel/connection.h @@ -128,14 +128,6 @@ class Connection Connection( const Connection< targetidentifierT >& rhs ) = default; Connection& operator=( const Connection< targetidentifierT >& rhs ) = default; - /** - * Get a pointer to an instance of a SecondaryEvent if this connection supports secondary events. - * - * To prevent erronous calls of this function on primary connections, the base class implementation - * below just contains `assert(false)`. - */ - SecondaryEvent* get_secondary_event(); - /** * Get all properties of this connection and put them into a dictionary. */ @@ -398,13 +390,6 @@ Connection< targetidentifierT >::trigger_update_weight( const size_t, throw IllegalConnection( "Connection does not support updates that are triggered by a volume transmitter." ); } -template < typename targetidentifierT > -SecondaryEvent* -Connection< targetidentifierT >::get_secondary_event() -{ - assert( false ); -} - } // namespace nest #endif /* CONNECTION_H */ diff --git a/nestkernel/connector_model.h b/nestkernel/connector_model.h index 80848ee7107..f7791319f9e 100644 --- a/nestkernel/connector_model.h +++ b/nestkernel/connector_model.h @@ -59,6 +59,26 @@ enum class ConnectionModelProperties : unsigned REQUIRES_CLOPATH_ARCHIVING = 1 << 6, REQUIRES_URBANCZIK_ARCHIVING = 1 << 7 }; +} + +namespace +{ // FIXME: utils namespace? + +template < typename, typename = void > +struct has_get_secondary_event_t : std::false_type +{}; + +template < typename ConnectionT > +struct has_get_secondary_event_t< + ConnectionT, + std::void_t< + decltype( std::declval< ConnectionT >().get_secondary_event( ) ) > > : public std::true_type +{}; + +} // end of FIXME + +namespace nest +{ template <> struct EnableBitMaskOperators< ConnectionModelProperties > @@ -199,7 +219,16 @@ class GenericConnectorModel : public ConnectorModel SecondaryEvent* get_secondary_event() override { - return default_connection_.get_secondary_event(); + constexpr bool is_primary = flag_is_set( ConnectionT::properties, nest::ConnectionModelProperties::IS_PRIMARY ); + constexpr bool has_get_secondary_event = has_get_secondary_event_t< ConnectionT >::value; + static_assert( is_primary xor has_get_secondary_event, + "Non-primary connections have to provide get_secondary_event()" ); + if constexpr ( ( not is_primary ) and has_get_secondary_event ) { + return default_connection_.get_secondary_event(); + } else { + // unreachable code + return nullptr; + } } ConnectionT const& diff --git a/nestkernel/connector_model_impl.h b/nestkernel/connector_model_impl.h index 5de25ec15a3..2adb4be7c7f 100644 --- a/nestkernel/connector_model_impl.h +++ b/nestkernel/connector_model_impl.h @@ -68,8 +68,9 @@ GenericConnectorModel< ConnectionT >::clone( std::string name, synindex syn_id ) ConnectorModel* new_cm = new GenericConnectorModel( *this, name ); // calls copy construtor new_cm->set_syn_id( syn_id ); - const bool is_primary = new_cm->has_property( ConnectionModelProperties::IS_PRIMARY ); - if ( not is_primary ) + constexpr bool is_primary = flag_is_set( ConnectionT::properties, nest::ConnectionModelProperties::IS_PRIMARY ); + constexpr bool has_get_secondary_event = has_get_secondary_event_t< ConnectionT >::value; + if constexpr ( ( not is_primary ) and has_get_secondary_event ) { new_cm->get_secondary_event()->add_syn_id( syn_id ); }