Utils/Console: Add ValueRange utility
[senf.git] / PPI / MultiConnectorMixin.hh
index e607c48..b386e01 100644 (file)
@@ -54,20 +54,26 @@ namespace ppi {
     // output, otherwise the second overload.
 
     /** \brief Connect MultiConnector source to arbitrary target
+
         Additional implementations with 0..SENF_MULTI_CONNECTOR_MAX_ARGS arguments.
+
         \related module::MultiConnectorMixin
      */
-    template <class Source, class Target, class A1>
-    Source::ConnectorType & connect(Source & source, Target & target, A1 const & a1);
+    template <class MultiConnectorSource, class Target, class A1>
+    MultiConnectorSource::ConnectorType & connect(
+        MultiConnectorSource & source, Target & target, A1 const & a1);
     
     /** \brief Connect arbitrary source to MultiConnector target
+
         Additional implementations with 0..SENF_MULTI_CONNECTOR_MAX_ARGS arguments.
+
         \related module::MultiConnectorMixin
      */
-    template <class Source, class Target>
-    Target::ConnectorType & connect(Source & source, Target & target, A1 const & a1);
+    template <class Source, class MultiConnectorTarget, class A1>
+    MultiConnectorTarget::ConnectorType & connect(
+        Source & source, MultiConnectorTarget & target, A1 const & a1);
 
-#endif
+#else
 
     // Include 'senf::ppi::namespace member declarations' from MultiConnectorMixin.mpp
 #   define BOOST_PP_ITERATION_PARAMS_1 (4, ( \
@@ -77,6 +83,8 @@ namespace ppi {
             2 ))
 #   include BOOST_PP_ITERATE()
 
+#endif
+
 namespace module {
 
     /** \brief Multi connector management
@@ -85,7 +93,8 @@ namespace module {
         output connectors.
         \code
         class MyModule 
-            : public senf::ppi::module::MultiConnectorMixin<
+            : public senf::ppi::module::Modulem,
+              public senf::ppi::module::MultiConnectorMixin<
                   MyModule, senf::ppi::connector::ActiveInput<> >
         {
             SENF_PPI_MODULE(MyModule);
@@ -153,12 +162,12 @@ namespace module {
 
         \par "Example:" senf::ppi::module::AnnotationRouter
 
-        \section senf_ppi_multiconnector_connect Connect and additional \c connectorSetup() arguments
+        \section senf_ppi_multiconnector_connect Connect and additional connectorSetup() arguments
 
         When connecting to a module using the MultiConnectorMixin, every new connect call will
         allocate a new connector
         \code
-        MuModule muModule;
+        MyModule muModule;
         
         senf::ppi::connect(someModule, myModule);
         \endcode
@@ -176,11 +185,45 @@ namespace module {
         {
             container().insert(container().begin()+index, container().pop_back().release());
         }
+        \endcode
 
         \par "Advanced note:" These additional arguments are always passed by const-reference. If
             you need to pass a non-const reference, declare the \c connectorSetup() argument as
             non-const reference and wrap the real argument using \c boost::ref() (The reason for
             this is known as 'The forwarding problem'
+
+        \section senf_ppi_multiconnector_advanced Advanced usage: Managing your own container
+
+        If you need to use a completely different type of container, you can take over the container
+        management yourself. To do this, pass \c void as container type and change \c
+        connectorSetup() to take an \c std::auto_ptr as argument. \c connectorSetup() must ensure to
+        save this connector in some container or throw an exception
+        \code
+        class MyModule 
+            : public senf::ppi::module::Module,
+              public senf::ppi::module::MultiConnectorMixin<
+                  MyModule, senf::ppi::connector::ActiveInput<>, void, void >
+        {
+            SENF_PPI_MODULE(MyModule);
+        public:
+            // ...
+
+        private:
+            void connectorSetup(std::auto_ptr<ConnectorType> conn, unsigned p)
+            {
+                if (p>connectors_.size())
+                   throw SomeErrorException();
+                route(*conn, output);
+                connectors_.insert(connectors_.begin()+p,conn);
+            }
+
+            boost::ptr_vector<ConnectorType> connectors_;
+        };
+        \endcode
+        \warning You must make absolutely sure the connector does not get deleted when returning
+            normally from \c connectorSetup(): The connector \e must be saved somewhere
+            successfully, otherwise your code will break.
+
      */
     template <class Self_, 
               class ConnectorType_, 
@@ -191,14 +234,15 @@ namespace module {
         : private detail::MultiConnectorSelectBase<ConnectorType_>::type
     {
     public:
-        typedef ConnectorType_ ConnectorType;
+        typedef ConnectorType_ ConnectorType; ///< Type of MultiConnector connector
 
     protected:
-        typedef ContainerType_ ContainerType;
-        ContainerType_ & connectors();
+        typedef ContainerType_ ContainerType; ///< Type of connector container
+        ContainerType_ & connectors();        ///< Get connector container
+        ContainerType_ const & connectors() const; ///< Get connectors container (const)
 
     private:
-#ifdef DOXYGEN
+#if 0
         // For exposition only
         // Other implementations with 0..SENF_MULTI_CONNECTOR_MAX_ARGS arguments accordingly
 
@@ -218,6 +262,7 @@ namespace module {
                                                           Target & target,
                                                           A1 const & a1);
 #endif
+#ifndef DOXYGEN
 
         // Include 'MultiConnectorMixin member declaration' from MultiConnectorMixin.mpp
 #       define BOOST_PP_ITERATION_PARAMS_1 (4, ( \
@@ -226,10 +271,14 @@ namespace module {
             SENF_ABSOLUTE_INCLUDE_PATH(PPI/MultiConnectorMixin.mpp), \
             1 ))
 #       include BOOST_PP_ITERATE()
+
+#endif
         
         ContainerType_ connectors_;
     };
 
+#ifndef DOXYGEN
+
     template <class Self_,
               class ConnectorType_,
               class ContainerType_>
@@ -245,7 +294,7 @@ namespace module {
 
     private:
 
-#ifdef DOXYGEN
+#if 0
         // For exposition only
         // Other implementations with 0..SENF_MULTI_CONNECTOR_MAX_ARGS arguments accordingly
 
@@ -276,6 +325,48 @@ namespace module {
         
         ContainerType_ connectors_;
     };
+
+    template <class Self_, 
+              class ConnectorType_>
+    class MultiConnectorMixin<Self_,ConnectorType_,void,void>
+        : private detail::MultiConnectorSelectBase<ConnectorType_>::type
+    {
+    public:
+        typedef ConnectorType_ ConnectorType;
+
+    private:
+
+#if 0
+        // For exposition only
+        // Other implementations with 0..SENF_MULTI_CONNECTOR_MAX_ARGS arguments accordingly
+
+        tempalte <class A1>
+        ConnectorType_ & newConnector(A1 const & a1);
+
+        // See above for an additional note regarding the boost::enable_if in the real
+        // implementation
+        
+        template <class Source, class Target, class A1>
+        friend Source::ConnectorType & senf::ppi::connect(Source & source, 
+                                                          Target & target, 
+                                                          A1 const & a1);
+
+        template <class Source, class Target, class A1>
+        friend Target::ConnectorType & senf::ppi::connect(Source & source,
+                                                          Target & target,
+                                                          A1 const & a1);
+#endif
+
+        // Include 'MultiConnectorMixin member declaration' from MultiConnectorMixin.mpp
+#       define BOOST_PP_ITERATION_PARAMS_1 (4, ( \
+            0, \
+            SENF_MULTI_CONNECTOR_MAX_ARGS, \
+            SENF_ABSOLUTE_INCLUDE_PATH(PPI/MultiConnectorMixin.mpp), \
+            1 ))
+#       include BOOST_PP_ITERATE()
+    };
+
+#endif
         
 }}}