class similar to a function object?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Jef Driesen

    #1

    class similar to a function object?

    Suppose I have a datastructure (actually it's a graph) with one template
    parameter (the property P for each edge and vertex):

    struct graph<P>;
    struct vertex<P>;
    struct edge<P>;

    I also have an algorithm that modifies this datastructure. The basic
    outline of the algorithm is independent of the type of property. So I
    implemented a generic version of the algorithm and a function object for
    each type of property I need. In this way, adding a new property
    involves simply defining the property and implementing the function
    object. And that works great, however I have a question about the
    function object, which looks more or less like this:

    template <typename P>
    struct function_object {
    // Initialization
    void initialize(regi on<P>& r) const;
    void initialize(edge <P>& e) const;
    // Evaluation
    double evaluate(const edge<P>& e) const;
    };

    As you can see I declared it with a template parameter (and add no
    implementation) . For each type of property I add a specialization (with
    an implementation of course).

    struct my_property;

    template <>
    struct function_object <my_property{
    // Initialization
    void initialize(regi on<my_property> & r) const;
    void initialize(edge <my_property> & e) const;
    // Evaluation
    double evaluate(const edge<my_propert y>& e) const;
    };

    But I could as well have done this without using "function_objec t". Are
    there pros and/or contras against this design? Initially, my idea was to
    add only a specialization of the member functions only, and not the
    whole class, but that doesn't work.
  • Victor Bazarov

    #2
    Re: class similar to a function object?

    Jef Driesen wrote:
    Suppose I have a datastructure (actually it's a graph) with one
    template parameter (the property P for each edge and vertex):
    >
    struct graph<P>;
    struct vertex<P>;
    struct edge<P>;
    You mean, probably

    template<class Pstruct graph;
    template<class Pstruct vertex;
    template<class Pstruct edge;
    I also have an algorithm that modifies this datastructure.
    You mean, the graph struct (and all related)?
    The basic
    outline of the algorithm is independent of the type of property. So I
    implemented a generic version of the algorithm and a function object
    for each type of property I need. In this way, adding a new property
    involves simply defining the property and implementing the function
    object. And that works great, however I have a question about the
    function object, which looks more or less like this:
    >
    template <typename P>
    struct function_object {
    // Initialization
    void initialize(regi on<P>& r) const;
    void initialize(edge <P>& e) const;
    // Evaluation
    double evaluate(const edge<P>& e) const;
    };
    >
    As you can see I declared it with a template parameter (and add no
    implementation) . For each type of property I add a specialization
    (with an implementation of course).
    >
    struct my_property;
    >
    template <>
    struct function_object <my_property{
    // Initialization
    void initialize(regi on<my_property> & r) const;
    void initialize(edge <my_property> & e) const;
    // Evaluation
    double evaluate(const edge<my_propert y>& e) const;
    };
    >
    But I could as well have done this without using "function_objec t".
    Are there pros and/or contras against this design? Initially, my idea
    was to add only a specialization of the member functions only, and
    not the whole class, but that doesn't work.
    What doesn't work?

    template<>
    void
    function_object <my_property>:: initialize(regi on<my_property> & r) const
    {
    // blah
    }

    See FAQ 5.8.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask


    Comment

    • Michiel.Salters@tomtom.com

      #3
      Re: class similar to a function object?

      Jef Driesen wrote:
      Suppose I have a datastructure (actually it's a graph) with one template
      parameter (the property P for each edge and vertex):
      >
      struct graph<P>;
      struct vertex<P>;
      struct edge<P>;
      Not using boost::graph, then.
      I also have an algorithm that modifies this datastructure. The basic
      outline of the algorithm is independent of the type of property. So I
      implemented a generic version of the algorithm and a function object for
      each type of property I need.
      There is a one-to-one relation between function object and property?
      Or are there properties for which you could have multiple function
      objects?

      I.e. the sort algorithm accepts multiple function objects per type.
      I have a question about the function object, which looks like this:
      >
      template <typename P>
      struct function_object {
      // Initialization
      void initialize(regi on<P>& r) const;
      void initialize(edge <P>& e) const;
      // Evaluation
      double evaluate(const edge<P>& e) const;
      };
      Usually initialization is done in the constructor, of course. And
      evaluate
      is usually named operator(). You might want to inherit from
      std::unary_func tion
      to make it more STL-compatible.
      For each type of property I add a specialization with an implementation.
      >
      struct my_property;
      >
      template <>
      struct function_object <my_property{
      // Initialization
      void initialize(regi on<my_property> & r) const;
      void initialize(edge <my_property> & e) const;
      // Evaluation
      double evaluate(const edge<my_propert y>& e) const;
      };
      >
      But I could as well have done this without using "function_objec t". Are
      there pros and/or contras against this design?
      Pro: you can use function_object <Pas a default parameter to the
      algorithm.
      cf. std::less<Tfor std::sort.
      Contra: it's not compatible with STL or boost::graph.
      Initially, my idea was to add only a specialization of the member functions
      only, and not the whole class, but that doesn't work.
      Simple solution that often works: forward to a free function template,
      specialize/
      overload that.

      HTH,
      Michiel Salters

      Comment

      • Jef Driesen

        #4
        Re: class similar to a function object?

        Victor Bazarov wrote:
        Jef Driesen wrote:
        >Suppose I have a datastructure (actually it's a graph) with one
        >template parameter (the property P for each edge and vertex):
        >>
        >struct graph<P>;
        >struct vertex<P>;
        >struct edge<P>;
        >
        You mean, probably
        >
        template<class Pstruct graph;
        template<class Pstruct vertex;
        template<class Pstruct edge;
        Of course.
        >I also have an algorithm that modifies this datastructure.
        >
        You mean, the graph struct (and all related)?
        That is correct.
        >The basic
        >outline of the algorithm is independent of the type of property. So I
        >implemented a generic version of the algorithm and a function object
        >for each type of property I need. In this way, adding a new property
        >involves simply defining the property and implementing the function
        >object. And that works great, however I have a question about the
        >function object, which looks more or less like this:
        >>
        >template <typename P>
        >struct function_object {
        > // Initialization
        > void initialize(regi on<P>& r) const;
        > void initialize(edge <P>& e) const;
        > // Evaluation
        > double evaluate(const edge<P>& e) const;
        >};
        >>
        >As you can see I declared it with a template parameter (and add no
        >implementation ). For each type of property I add a specialization
        >(with an implementation of course).
        >>
        >struct my_property;
        >>
        >template <>
        >struct function_object <my_property{
        > // Initialization
        > void initialize(regi on<my_property> & r) const;
        > void initialize(edge <my_property> & e) const;
        > // Evaluation
        > double evaluate(const edge<my_propert y>& e) const;
        >};
        >>
        >But I could as well have done this without using "function_objec t".
        >Are there pros and/or contras against this design? Initially, my idea
        >was to add only a specialization of the member functions only, and
        >not the whole class, but that doesn't work.
        >
        What doesn't work?
        Providing only implementations for the initialize/evaluate functions
        (without a declaring the full class template <struct
        function_object <my_propertyabo ve). Because I think that is not allowed
        by the C++ language and it will make it impossible to add different
        member variables for each type of property.

        template <>
        struct function_object <my_property1 {
        int m_data; // suppose I need ints here
        }

        template <>
        struct function_object <my_property2 {
        double m_data; // suppose I need doubles here
        }

        But that (or writing the code) was not my main problem (because i
        already have it working. I was wondering if there is an advantage over
        doing something like this:

        struct my_function_obj ect {
        // Initialization
        void initialize(regi on<my_property> & r) const;
        void initialize(edge <my_property> & e) const;
        // Evaluation
        double evaluate(const edge<my_propert y>& e) const;
        };

        e.g., without using the templated "function_objec t" from my first post?

        Comment

        • Victor Bazarov

          #5
          Re: class similar to a function object?

          Jef Driesen wrote:
          [..]
          But that (or writing the code) was not my main problem (because i
          already have it working. I was wondering if there is an advantage over
          doing something like this:
          >
          struct my_function_obj ect {
          // Initialization
          void initialize(regi on<my_property> & r) const;
          void initialize(edge <my_property> & e) const;
          // Evaluation
          double evaluate(const edge<my_propert y>& e) const;
          };
          >
          e.g., without using the templated "function_objec t" from my first
          post?
          Does 'my_function_ob ject' have any data members (any state)? So far
          nothing says that the functions need to be (a) members of a class and
          (b) non-static members of that class.

          What does 'my_function_ob ject' do?

          V
          --
          Please remove capital 'A's when replying by e-mail
          I do not respond to top-posted replies, please don't ask


          Comment

          • Jef Driesen

            #6
            Re: class similar to a function object?

            Victor Bazarov wrote:
            Jef Driesen wrote:
            >[..]
            >But that (or writing the code) was not my main problem (because i
            >already have it working). I was wondering if there is an advantage over
            >doing something like this:
            >>
            >struct my_function_obj ect {
            > // Initialization
            > void initialize(regi on<my_property> & r) const;
            > void initialize(edge <my_property> & e) const;
            > // Evaluation
            > double evaluate(const edge<my_propert y>& e) const;
            >};
            >>
            >e.g., without using the templated "function_objec t" from my first
            >post?
            >
            Does 'my_function_ob ject' have any data members (any state)? So far
            nothing says that the functions need to be (a) members of a class and
            (b) non-static members of that class.
            >
            What does 'my_function_ob ject' do?
            One of the properties is something like this:

            struct my_property {
            matrix<doubleal pha, mu;
            double lambda;
            }

            The other one has two alpha's and two mu's (for horizontal and vertical
            directions).

            After constructing the graph, all properties have default values
            (default constructor). Simply because the data needed to create the
            graph is not the same as the data to calculate the properties, and is
            also equal for all kind of properties. Only the algorithm needs those
            properties to do its job. That's why I have those two initialize
            functions. It also needs to be able to compare two vertices (=edge) and
            sort edges. The evaluate function is used for that.

            The my_function_obj ect's have several data members. The first one
            contains basically one 3D image and the other one two such images.

            BTW, in the code from my first post, I mentioned both a vertex and a
            region class, but those are the same. In my application a vertex is a
            region of image pixels, hence the different name.

            Comment

            • Victor Bazarov

              #7
              Re: class similar to a function object?

              "Jef Driesen" <jefdriesen@hot mail.com.invali dwrote...
              Victor Bazarov wrote:
              >Jef Driesen wrote:
              >>[..]
              >>But that (or writing the code) was not my main problem (because i
              >>already have it working). I was wondering if there is an advantage over
              >>doing something like this:
              >>>
              >>struct my_function_obj ect {
              >> // Initialization
              >> void initialize(regi on<my_property> & r) const;
              >> void initialize(edge <my_property> & e) const;
              >> // Evaluation
              >> double evaluate(const edge<my_propert y>& e) const;
              >>};
              >>>
              >>e.g., without using the templated "function_objec t" from my first
              >>post?
              >>
              >Does 'my_function_ob ject' have any data members (any state)? So far
              >nothing says that the functions need to be (a) members of a class and
              >(b) non-static members of that class.
              >>
              >What does 'my_function_ob ject' do?
              >
              [..]
              >
              The my_function_obj ect's have several data members. The first one contains
              basically one 3D image and the other one two such images.
              >
              BTW, in the code from my first post, I mentioned both a vertex and a
              region class, but those are the same. In my application a vertex is a
              region of image pixels, hence the different name.
              I am still not convinced that you actually need a class
              'my_function_ob ject'.
              All you need it for is to calculate something. It doesn't seem to need any
              state. You can have separate functions and pass your 3D images to them as
              arguments.

              If you're struggling with instantiating the function_object thingamajig,
              just get rid of it and putt the 'initialize' and 'evaluate' functions out
              and make them templates (if necessary, of which I am not convinced either).
              Then specialize them, if you need that.

              Don't rush to reply. Think about it a bit. It is possible that you have
              not provided enough information for me to understand why you need those
              functions in a class. It doesn't mean you don't need them in a class, it
              just means I don't see it yet. Perhaps you could describe your problem
              from a slightly different angle, and it will open up to me (and to you).
              So far you have some properties and unrelated algorithms which you want
              OOH to unify under a class template and OTOH break apart by specialising.
              And hereby lies the problem, methinks.

              V
              --
              Please remove capital 'A's when replying by e-mail
              I do not respond to top-posted replies, please don't ask


              Comment

              • Jef Driesen

                #8
                Re: class similar to a function object?

                Michiel.Salters @tomtom.com wrote:
                Jef Driesen wrote:
                >Suppose I have a datastructure (actually it's a graph) with one template
                >parameter (the property P for each edge and vertex):
                >>
                >struct graph<P>;
                >struct vertex<P>;
                >struct edge<P>;
                >
                Not using boost::graph, then.
                At some point, I considered using it, but I already had a more or less
                working implementation and decided not to rewrite everything using
                boost::graph.
                >I also have an algorithm that modifies this datastructure. The basic
                >outline of the algorithm is independent of the type of property. So I
                >implemented a generic version of the algorithm and a function object for
                >each type of property I need.
                >
                There is a one-to-one relation between function object and property?
                Or are there properties for which you could have multiple function
                objects?
                >
                I.e. the sort algorithm accepts multiple function objects per type.
                Each property has its own function object, because they are calculated
                from different kind of data.
                >I have a question about the function object, which looks like this:
                >>
                >template <typename P>
                >struct function_object {
                > // Initialization
                > void initialize(regi on<P>& r) const;
                > void initialize(edge <P>& e) const;
                > // Evaluation
                > double evaluate(const edge<P>& e) const;
                >};
                >
                Usually initialization is done in the constructor, of course.
                The problem is that the graph does not know how to calculate properties.
                And I also need the graph itself to calculate the properties. During
                construction of the graph (and thus also the regions), I can't calculate
                the properties. (I think it can be done if I really want, but I'm afraid
                it will be too slow incrementally updating matrices compared to doing it
                once in a batch).
                And evaluate
                is usually named operator(). You might want to inherit from
                std::unary_func tion
                to make it more STL-compatible.
                I also need sorting, and for that I created a simple helper function
                object in STL-style.
                >For each type of property I add a specialization with an implementation.
                >>
                >struct my_property;
                >>
                >template <>
                >struct function_object <my_property{
                > // Initialization
                > void initialize(regi on<my_property> & r) const;
                > void initialize(edge <my_property> & e) const;
                > // Evaluation
                > double evaluate(const edge<my_propert y>& e) const;
                >};
                >>
                >But I could as well have done this without using "function_objec t". Are
                >there pros and/or contras against this design?
                >
                Pro: you can use function_object <Pas a default parameter to the
                algorithm.
                cf. std::less<Tfor std::sort.
                Isn't that almost the same as what I have now?

                template <typename P>
                void apply_algorithm (graph<P>& g, const function_object <P>& p)
                Contra: it's not compatible with STL or boost::graph.
                Since I'm not using boost::graph, that disadvantage is not so important.
                >Initially, my idea was to add only a specialization of the member functions
                >only, and not the whole class, but that doesn't work.
                >
                Simple solution that often works: forward to a free function template,
                specialize/
                overload that.
                I didn't even think about that. But that will not work if the different
                function objects need different member variables.

                Comment

                • Jef Driesen

                  #9
                  Re: class similar to a function object?

                  Victor Bazarov wrote:
                  Jef Driesen wrote...
                  >[..]
                  >
                  I am still not convinced that you actually need a class
                  'my_function_ob ject'.
                  All you need it for is to calculate something. It doesn't seem to need any
                  state. You can have separate functions and pass your 3D images to them as
                  arguments.
                  If I had separate functions, how would my algorithm know about the 3D
                  images? And also which variant to call, the one with only one 3D image
                  as parameter, or the one with two 3D images? With 'my_function_ob ject',
                  I can add them as member variables and have a version which takes one 3D
                  image in the constructor and one with two 3D images. And then pass the
                  function object (which knows how to do the calculations and has all the
                  extra data) and the graph (which knows the layout of the regions and its
                  pixels) to my algorithm (where everything is glued together).
                  If you're struggling with instantiating the function_object thingamajig,
                  just get rid of it and putt the 'initialize' and 'evaluate' functions out
                  and make them templates (if necessary, of which I am not convinced either).
                  Then specialize them, if you need that.
                  >
                  Don't rush to reply. Think about it a bit. It is possible that you have
                  not provided enough information for me to understand why you need those
                  functions in a class. It doesn't mean you don't need them in a class, it
                  just means I don't see it yet. Perhaps you could describe your problem
                  from a slightly different angle, and it will open up to me (and to you).
                  So far you have some properties and unrelated algorithms which you want
                  OOH to unify under a class template and OTOH break apart by specialising.
                  And hereby lies the problem, methinks.
                  I will try to reformulate what I'm trying to do.

                  First step is the constructing of the graph datastructure. The graph is
                  created from a 2D image, where each pixel is a label. A vertex in the
                  graph represent a group of pixels with the same label (e.g. a region).
                  An edge represents a link between two such regions, adjacent to each
                  other (e.g. neighbors).

                  Second step is my algorithm. First, all properties for the regions are
                  calculated. A property for a region is calculated from the corresponding
                  pixels of one or two 3D images (depending on the type of property)
                  inside that region. The property itself is some statistical data, like
                  average vector and covariance matrix. When that is ready, the properties
                  are calculated for all edges. Properties for an edge are simply the same
                  statistical properties, but for the union of both regions. They can be
                  calculated from the properties of the two regions directly (if
                  possible), or from the underlying 3D image data again. After that edges
                  are evaluated against a threshold and suitable edges are selected and
                  sorted according to the return value of the evaluate function. Finally,
                  the graph is modified and properties are updated again.

                  Comment

                  • Victor Bazarov

                    #10
                    Re: class similar to a function object?

                    Jef Driesen wrote:
                    Victor Bazarov wrote:
                    >Jef Driesen wrote...
                    >>[..]
                    >>
                    >I am still not convinced that you actually need a class
                    >'my_function_o bject'.
                    >All you need it for is to calculate something. It doesn't seem to
                    >need any state. You can have separate functions and pass your 3D
                    >images to them as arguments.
                    >
                    If I had separate functions, how would my algorithm know about the 3D
                    images?
                    But you don't have a single algorithm, do you? One uses one image, the
                    other one uses two. So, you need two separate functions, one with one
                    extra argument of type 'my3Dimage const&', the other needs two extra
                    arguments.
                    And also which variant to call, the one with only one 3D image
                    as parameter, or the one with two 3D images?
                    Shouldn't the caller know that? You are going to stuff them into your
                    'function_objec t' somehow, so at some point the code needs to know how
                    many images to pass and to whom...
                    With
                    'my_function_ob ject', I can add them as member variables and have a
                    version which takes one 3D image in the constructor and one with two
                    3D images.
                    Yes, just like you can have two separate function_object classes. Just
                    like you can have no classes whatsoever. The code that creates the
                    objects (right now) can just as well call the 'initialize' functions
                    without the object, can't it?
                    And then pass the function object (which knows how to do
                    the calculations and has all the extra data) and the graph (which
                    knows the layout of the regions and its pixels) to my algorithm
                    (where everything is glued together).
                    Again, it's not a single algorithm, is it? At least so far I've not
                    see a single algorithm. And if it is a single algorithm, then you are
                    much better off actually employing polymorphism, IOW, having both of
                    your 'function_objec ts' derive from an abstract class and override
                    your 'initialize' and 'evaluate' functions... Since you've not shown
                    how your 'my_function_ob ject' instance is going to be used, I have
                    not formed any opinion on the matter except that it sounds unneededly
                    complicated.
                    >If you're struggling with instantiating the function_object
                    >thingamajig, just get rid of it and putt the 'initialize' and
                    >'evaluate' functions out and make them templates (if necessary, of
                    >which I am not convinced either). Then specialize them, if you need
                    >that. Don't rush to reply. Think about it a bit. It is possible that
                    >you
                    >have not provided enough information for me to understand why you
                    >need those functions in a class. It doesn't mean you don't need
                    >them in a class, it just means I don't see it yet. Perhaps you
                    >could describe your problem from a slightly different angle, and it
                    >will open up to me (and to you). So far you have some properties and
                    >unrelated algorithms which you want OOH to unify under a class
                    >template and OTOH break apart by specialising. And hereby lies the
                    >problem, methinks.
                    >
                    I will try to reformulate what I'm trying to do.
                    >
                    First step is the constructing of the graph datastructure. The graph
                    is created from a 2D image, where each pixel is a label. A vertex in
                    the graph represent a group of pixels with the same label (e.g. a
                    region). An edge represents a link between two such regions, adjacent
                    to each other (e.g. neighbors).
                    That looks like you need a function like

                    template<class Pgraph<PcreateG raph(my2Dimage const&);

                    where 'graph' would contain the vertices and edges necessary to define
                    your topology. No need for a special functor as of yet.
                    Second step is my algorithm. First, all properties for the regions are
                    calculated. A property for a region is calculated from the
                    corresponding pixels of one or two 3D images (depending on the type
                    of property) inside that region. The property itself is some
                    statistical data, like average vector and covariance matrix. When
                    that is ready, the properties are calculated for all edges.
                    Properties for an edge are simply the same statistical properties,
                    but for the union of both regions. They can be calculated from the
                    properties of the two regions directly (if possible), or from the
                    underlying 3D image data again. After that edges are evaluated
                    against a threshold and suitable edges are selected and sorted
                    according to the return value of the evaluate function. Finally, the
                    graph is modified and properties are updated again.
                    Uh... I am not seeing it...

                    template<class P>
                    void calculateProper ties(region<P>& , my3Dimage const*);

                    template<class P>
                    void calculateProper ties(edge<P>&, my3Dimage const*);

                    template<class P>
                    void calculateProper ties(graph<P>&, my3Dimage const*);

                    The pointer is either one image, or two images or as many as you like,
                    put into an array. Or you can have a pointer to pointer, which could
                    be an array of pointers to image...

                    Where is the need for a 'function_objec t'?

                    V
                    --
                    Please remove capital 'A's when replying by e-mail
                    I do not respond to top-posted replies, please don't ask


                    Comment

                    • Jef Driesen

                      #11
                      Re: class similar to a function object?

                      Victor Bazarov wrote:
                      Jef Driesen wrote:
                      >Victor Bazarov wrote:
                      >>Jef Driesen wrote...
                      >>>[..]
                      >>I am still not convinced that you actually need a class
                      >>'my_function_ object'.
                      >>All you need it for is to calculate something. It doesn't seem to
                      >>need any state. You can have separate functions and pass your 3D
                      >>images to them as arguments.
                      >If I had separate functions, how would my algorithm know about the 3D
                      >images?
                      >
                      But you don't have a single algorithm, do you? One uses one image, the
                      other one uses two. So, you need two separate functions, one with one
                      extra argument of type 'my3Dimage const&', the other needs two extra
                      arguments.
                      I only have one algorithm and it takes as argument the graph, the
                      function object and some less important parameters (like a threshold).

                      template <typename P>
                      void apply_algorithm (graph<P>& g, const function_object <P>& p, double
                      threshold)
                      {
                      std::list< edge<P selected;

                      // Initialize regions
                      for each region r in g
                      p.initialize(r) ;

                      // Initialize edges
                      for each edge e in g {
                      p.initialize(e) ;
                      if p.evaluate(e) threshold
                      selected.push_b ack(e);
                      }

                      // Sort selected edges
                      selected.sort(c ompare_edges<P> (p);

                      // Some more stuff here...
                      }

                      Sorting does use an extra helper function object:

                      template <typename P>
                      struct compare_edges : public std::binary_fun ction<edge<P>, edge<P>,
                      bool{
                      const function_object <P>& m_p;

                      compare_edges(c onst function_object <P>& p
                      : m_p(p) {}

                      bool operator()(cons t edge<P>& lhs, const edge<P>& rhs) const
                      {
                      return m_p.evaluate(lh s) m_p.evaluate(rh s);
                      }
                      };
                      >And also which variant to call, the one with only one 3D image
                      >as parameter, or the one with two 3D images?
                      >
                      Shouldn't the caller know that? You are going to stuff them into your
                      'function_objec t' somehow, so at some point the code needs to know how
                      many images to pass and to whom...
                      As you can see, the algorithm itself does not need to know if there were
                      one or two 3D images. That is handled by my function_object :

                      struct function_object 1 {
                      image3d m_image;
                      function_object 1(image3d image)
                      : m_image(image) {}
                      }

                      struct function_object 2 {
                      image3d m_image1, m_image2;
                      function_object 1(image3d image1, image3d image2)
                      : m_image1(image1 ), m_image2(image2 ) {}
                      }

                      and with different implementations of the evaluate/initialize functions
                      of course.
                      >With
                      >'my_function_o bject', I can add them as member variables and have a
                      >version which takes one 3D image in the constructor and one with two
                      >3D images.
                      >
                      Yes, just like you can have two separate function_object classes. Just
                      like you can have no classes whatsoever. The code that creates the
                      objects (right now) can just as well call the 'initialize' functions
                      without the object, can't it?
                      I'm not sure what you are trying to say here.
                      >And then pass the function object (which knows how to do
                      >the calculations and has all the extra data) and the graph (which
                      >knows the layout of the regions and its pixels) to my algorithm
                      >(where everything is glued together).
                      >
                      Again, it's not a single algorithm, is it? At least so far I've not
                      see a single algorithm. And if it is a single algorithm, then you are
                      much better off actually employing polymorphism, IOW, having both of
                      your 'function_objec ts' derive from an abstract class and override
                      your 'initialize' and 'evaluate' functions... Since you've not shown
                      how your 'my_function_ob ject' instance is going to be used, I have
                      not formed any opinion on the matter except that it sounds unneededly
                      complicated.
                      But how can I use polymorphism here? Because their initialize/evaluate
                      functions have a different type of argument. They are both regions or
                      edges, but with a different type for the template parameter P.
                      >>If you're struggling with instantiating the function_object
                      >>thingamajig , just get rid of it and putt the 'initialize' and
                      >>'evaluate' functions out and make them templates (if necessary, of
                      >>which I am not convinced either). Then specialize them, if you need
                      >>that. Don't rush to reply. Think about it a bit. It is possible that
                      >>you
                      >>have not provided enough information for me to understand why you
                      >>need those functions in a class. It doesn't mean you don't need
                      >>them in a class, it just means I don't see it yet. Perhaps you
                      >>could describe your problem from a slightly different angle, and it
                      >>will open up to me (and to you). So far you have some properties and
                      >>unrelated algorithms which you want OOH to unify under a class
                      >>template and OTOH break apart by specialising. And hereby lies the
                      >>problem, methinks.
                      >I will try to reformulate what I'm trying to do.
                      >>
                      >First step is the constructing of the graph datastructure. The graph
                      >is created from a 2D image, where each pixel is a label. A vertex in
                      >the graph represent a group of pixels with the same label (e.g. a
                      >region). An edge represents a link between two such regions, adjacent
                      >to each other (e.g. neighbors).
                      >
                      That looks like you need a function like
                      >
                      template<class Pgraph<PcreateG raph(my2Dimage const&);
                      >
                      where 'graph' would contain the vertices and edges necessary to define
                      your topology. No need for a special functor as of yet.
                      That is more or less what I have now, except that createGraph is not
                      separate function, but a constructor of the graph. You are also correct
                      that there is no special functor involved here.
                      >Second step is my algorithm. First, all properties for the regions are
                      >calculated. A property for a region is calculated from the
                      >correspondin g pixels of one or two 3D images (depending on the type
                      >of property) inside that region. The property itself is some
                      >statistical data, like average vector and covariance matrix. When
                      >that is ready, the properties are calculated for all edges.
                      >Properties for an edge are simply the same statistical properties,
                      >but for the union of both regions. They can be calculated from the
                      >properties of the two regions directly (if possible), or from the
                      >underlying 3D image data again. After that edges are evaluated
                      >against a threshold and suitable edges are selected and sorted
                      >according to the return value of the evaluate function. Finally, the
                      >graph is modified and properties are updated again.
                      >
                      Uh... I am not seeing it...
                      >
                      template<class P>
                      void calculateProper ties(region<P>& , my3Dimage const*);
                      >
                      template<class P>
                      void calculateProper ties(edge<P>&, my3Dimage const*);
                      >
                      template<class P>
                      void calculateProper ties(graph<P>&, my3Dimage const*);
                      >
                      The pointer is either one image, or two images or as many as you like,
                      put into an array. Or you can have a pointer to pointer, which could
                      be an array of pointers to image...
                      >
                      Where is the need for a 'function_objec t'?
                      With those calculateProper ties functions, I will need to pass the
                      my3Dimage image(s) to the algorithm too. And that is exactly what I
                      tried to avoid in the first place. What if I need a third type of
                      property, which does not need to be calculated from one or more 3D
                      images, but some other type of data? In this case the algorithm will
                      stay the same, but that will not be true for the calculateProper ties
                      functions. With the function_object , different data can be passed to the
                      constructor, but the definition of the evaluate/initialize functions can
                      remain the same (not the implemantation of course).

                      Comment

                      • Victor Bazarov

                        #12
                        Re: class similar to a function object?

                        Jef Driesen wrote:
                        [..]
                        With those calculateProper ties functions, I will need to pass the
                        my3Dimage image(s) to the algorithm too. And that is exactly what I
                        tried to avoid in the first place. What if I need a third type of
                        property, which does not need to be calculated from one or more 3D
                        images, but some other type of data? In this case the algorithm will
                        stay the same, but that will not be true for the calculateProper ties
                        functions. With the function_object , different data can be passed to
                        the constructor, but the definition of the evaluate/initialize
                        functions can remain the same (not the implemantation of course).
                        OK, I seem to understand better now, thanks for your patience.

                        Remember I spoke of polymorphism? Forget it. Apparently, due to
                        your choices, you need your algorithm to be expressed in terms of
                        templates, so let it be.

                        I think the problem I had with your inquiry stemmed from the fact
                        that the centerpoint class template was named so generically (pun
                        is not intended), "function_objec t". What you probably should have
                        named it is "initialiser_an d_evaluator". That would take out all
                        confusion.

                        And, yes, I think it's a decent design overall. The only side
                        effect of using templates is an unfortunate need to replicate all
                        the algorithms for all property types. Had it been written in
                        terms of abstract graph and edges/regions, and with the use of
                        some abstract initialiser_and _evaluator, you could have simply
                        supplied the pointers to those, and implement them as you wish,
                        even as template specialisations . In that case you'd have only
                        one algorithm implementation function.

                        V
                        --
                        Please remove capital 'A's when replying by e-mail
                        I do not respond to top-posted replies, please don't ask


                        Comment

                        • Jef Driesen

                          #13
                          Re: class similar to a function object?

                          Victor Bazarov wrote:
                          Jef Driesen wrote:
                          >[..]
                          >With those calculateProper ties functions, I will need to pass the
                          >my3Dimage image(s) to the algorithm too. And that is exactly what I
                          >tried to avoid in the first place. What if I need a third type of
                          >property, which does not need to be calculated from one or more 3D
                          >images, but some other type of data? In this case the algorithm will
                          >stay the same, but that will not be true for the calculateProper ties
                          >functions. With the function_object , different data can be passed to
                          >the constructor, but the definition of the evaluate/initialize
                          >functions can remain the same (not the implemantation of course).
                          >
                          OK, I seem to understand better now, thanks for your patience.
                          No problem at all. Since you took the time to have a look at my problem,
                          I have to thank you for your patience!
                          Remember I spoke of polymorphism? Forget it. Apparently, due to
                          your choices, you need your algorithm to be expressed in terms of
                          templates, so let it be.
                          >
                          I think the problem I had with your inquiry stemmed from the fact
                          that the centerpoint class template was named so generically (pun
                          is not intended), "function_objec t". What you probably should have
                          named it is "initialiser_an d_evaluator". That would take out all
                          confusion.
                          If I had known that in advance :-) What's in a name?
                          And, yes, I think it's a decent design overall. The only side
                          effect of using templates is an unfortunate need to replicate all
                          the algorithms for all property types. Had it been written in
                          terms of abstract graph and edges/regions, and with the use of
                          some abstract initialiser_and _evaluator, you could have simply
                          supplied the pointers to those, and implement them as you wish,
                          even as template specialisations . In that case you'd have only
                          one algorithm implementation function.
                          I don't see how I could use an abstract graph/node/edge class and still
                          being able to associate a property with the nodes and edges. Is that
                          even possible without using templates?

                          Comment

                          • Victor Bazarov

                            #14
                            Re: class similar to a function object?

                            Jef Driesen wrote:
                            [..]
                            I don't see how I could use an abstract graph/node/edge class and
                            still being able to associate a property with the nodes and edges. Is
                            that even possible without using templates?
                            I am not sure I have the time to into detail, to be honest. If your algo
                            is so generic that you want to make a template out of it; with a bit of
                            effort, and by making your graph, edge, and region classes abstract (and
                            deriving the "real" ones from them) you should be able to also define
                            your "initialiser_an d_evaluator" as an abstract class (and derive the
                            real ones from it).

                            Compile-time polymorphism and run-time polymorphism are often symmetrical,
                            only the run-time polymorphism can be taken a bit further with the help
                            of plug-ins and shared objects. It does not necessarily mean an advantage
                            in your case. Just an alternative approach.

                            V
                            --
                            Please remove capital 'A's when replying by e-mail
                            I do not respond to top-posted replies, please don't ask


                            Comment

                            • Jef Driesen

                              #15
                              Re: class similar to a function object?

                              Victor Bazarov wrote:
                              Jef Driesen wrote:
                              >[..]
                              >I don't see how I could use an abstract graph/node/edge class and
                              >still being able to associate a property with the nodes and edges. Is
                              >that even possible without using templates?
                              >
                              I am not sure I have the time to into detail, to be honest.
                              No problem, I already appreciated your help very much.
                              If your algo
                              is so generic that you want to make a template out of it; with a bit of
                              effort, and by making your graph, edge, and region classes abstract (and
                              deriving the "real" ones from them) you should be able to also define
                              your "initialiser_an d_evaluator" as an abstract class (and derive the
                              real ones from it).
                              I remember I encountered two kinds of problem when this approach (and
                              decided to use templates). The first one being that the 3 classes are
                              more or less nested:

                              struct graph_base {
                              struct edge_base {...}
                              struct node_base {...}
                              ...
                              }

                              That means if want to implement multiple types of graph (for different
                              properties), which share a lot of functionality (like constructing the
                              graph from the 2D image), I have to duplicate that code (handwritten,
                              not machine-generated like templates do). Because in my_graph I should
                              only create objects from the derived class (e.g. my_edge and store a
                              pointer to edge_base). And since graph_base doesn't know anything about
                              the derived classes, I can't implement it there.

                              struct my_graph : public graph_base {
                              struct my_edge : public edge_base {/*add properties here*/}
                              struct my_node : public node_base {/*add properties here*/}
                              }

                              Second problem was the initialiser_and _evaluator class

                              struct initialiser_and _evaluator {
                              initialize(edge _base& e) const;
                              initialize(node _base& n) const ;
                              evaluate(const edge_base& e) const;
                              }

                              If I overload this class, the functions will accept only
                              edge_base/node_base as arguments. And those don't have access to the
                              properties.

                              I'm sure there will be solutions for them, but I'm not aware of them.
                              Compile-time polymorphism and run-time polymorphism are often symmetrical,
                              only the run-time polymorphism can be taken a bit further with the help
                              of plug-ins and shared objects. It does not necessarily mean an advantage
                              in your case. Just an alternative approach.
                              Finally each one has different (dis)advantages ...

                              The run-time polymorphism would simplify the code in my main() a lot,
                              because currently I have (lots of) #ifdef's to pick one of the two
                              templates, which results in two different binaries. It works, but its
                              messy. Implementing a command line switch would be much easier with the
                              run-time polymorphism).

                              Comment

                              Working...