diff --git a/libnestutil/enum_bitfield.h b/libnestutil/enum_bitfield.h index 7c832f9e6b..2905745ae2 100644 --- a/libnestutil/enum_bitfield.h +++ b/libnestutil/enum_bitfield.h @@ -132,7 +132,7 @@ operator^=( Enum& lhs, Enum rhs ) } template < typename Enum > -bool +bool constexpr flag_is_set( const Enum en, const Enum flag ) { using underlying = typename std::underlying_type< Enum >::type; diff --git a/nestkernel/connection.h b/nestkernel/connection.h index 5ec146c963..45cbc7a8d7 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 504f8a8e80..90341811f5 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 > @@ -128,7 +148,7 @@ class ConnectorModel return name_; } - bool + bool constexpr has_property( const ConnectionModelProperties& property ) const { return flag_is_set( properties_, property ); @@ -199,7 +219,19 @@ 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 5de25ec15a..2adb4be7c7 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 ); }