Thread: Passing Functor as template parameter

  1. #1
    Registered User
    Join Date
    May 2008
    Location
    Paris
    Posts
    248

    Passing Functor as template parameter

    Hi,

    I want to parametrize the access to my 'valarray' data member with Accessor functors, so that clients of my library can use a callback to their own access function. These accessors just need to transform the row- and column-index to one overall index.

    For this purpose, I have made an interface class "MatrixAccessor":
    Code:
        class MatrixAccessor
        {
        public:
    	virtual size_t operator()(size_t i, size_t j);
        };
    with two derivations
    Code:
        class C_Accessor : public MatrixAccessor // for row-oriented memory access
        {
        public:
        C_Accessor(size_t nb_rows, size_t nb_cols) : _nbrows(nb_rows), _nbcols(nb_cols) {}
    	size_t operator()(size_t i, size_t j)
    	{
    	    return(i+j*_nbrows);
    	}
        private:
    	size_t _nbrows;
    	size_t _nbcols;
        };
    However, when I want to pass this Accessor via a template parameter, like in
    Code:
        template<typename T, typename Accessor = C_Accessor>
    	class Matrix
    	{
    	public:
              MatrixAccessor get_accessor() const {
                return this->static_cast<MatrixAccessor>(accessor);
              }
            };
    I will have to specialise this parameter in ALL member functions! And that's not exactly what will make my library user-friendly.

    Main problem: today's C++ standard does not allow default-specialisation of function template parameters.

    As a workaround, my idea is to not store the function object as an "Accessor" (template parameter), but as a "MatrixAccessor" (interface). I now pass the accessor as argument in the constructors, with as default value a static const object which I declare in the same header as the accessor declarations. However, this does not allow the interface from being an abstract base class, which I initially wanted.

    But, I do have the feeling that I'm not benefitting from static polymorphism as much as I could, and that this workaround will slow down algorithms with my library.
    Has someone got a better idea, or improvements to my idea?

    Thanks a lot!!!


    edit:

    The constructor argument will be a pointer to MatrixAccessor, of course necessary to call the correct 'operator()'. The base class can now remain a pure abstract class.
    Last edited by MarkZWEERS; 11-09-2008 at 06:56 AM.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Why do you need the MatrixAccessor hierachy?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    May 2008
    Location
    Paris
    Posts
    248
    Do you mean the derivation of my accessors from "MatrixAccessor" ? Because I want to store a pointer to it in my class, while not knowing which type I will get.
    This is for me the great advantage of passing the functor as template parameter, but I just don't want to specify it everywhere...

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Do you mean the derivation of my accessors from "MatrixAccessor" ? Because I want to store a pointer to it in my class, while not knowing which type I will get.
    If that is the case, then you should be storing an Accessor*, not a MatrixAccessor*, otherwise the Accessor template parameter is useless. get_accessor() should not return a MatrixAccessor*, much less a MatrixAccessor (which leads to type slicing), but should return an Accessor*.

    Your MatrixAccessor class have operator() as a pure virtual, and it should also have a virtual destructor.

    That said, I am not sure why you want to mix the run time polymorphism of the class hierarchy with the compile type polymorphism of the template parameter. std::set does something similiar by allowing a comparison function object to be provided at run time, but the type of the comparison function object is fixed at compile time.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User
    Join Date
    May 2008
    Location
    Paris
    Posts
    248
    Perhaps my explanation was not clear.

    The solution of passing the functor as template parameter has my preference, since then I won't use dynamic polymorphism at all. In that case I won't store a pointer to MatrixAccessor, but an object.

    But since I cannot set a default specialisation for the accessor in the template (member) functions, users will have to specialise this parameter every time they use it. And this I don't want.

    So that's why I'll go back to the C-style functors: passing a pointer to a function as constructor argument and storing this pointer. Then I'll have to use dynamic polymorphism.

    My question was basically: Can I use static polymorphism for the accessor but without having to specialise for all (member) functions the parameter?

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    The solution of passing the functor as template parameter has my preference, since then I won't use dynamic polymorphism at all. In that case I won't store a pointer to MatrixAccessor, but an object.
    Right. So what's wrong with:
    Code:
    template<typename T, typename Accessor = C_Accessor>
    class Matrix
    {
    public:
        // ...
    
        Accessor get_accessor() const
        {
            return accessor;
        }
    private:
        Accessor accessor;
    };
    But since I cannot set a default specialisation for the accessor in the template (member) functions, users will have to specialise this parameter every time they use it.
    Your users can instantiate the template with the desired accessor type, can they not?

    My question was basically: Can I use static polymorphism for the accessor but without having to specialise for all (member) functions the parameter?
    Yes, by instantiating the template with the desired template arguments.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Registered User
    Join Date
    May 2008
    Location
    Paris
    Posts
    248
    Hmmm... yes my fear actually only holds for free functions or operators, but then I won't need this template parameter anyway.
    Thanks!!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  2. error: template with C linkage
    By michaels-r in forum C++ Programming
    Replies: 3
    Last Post: 05-17-2006, 08:11 AM
  3. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  4. Please Help - Problem with Compilers
    By toonlover in forum C++ Programming
    Replies: 5
    Last Post: 07-23-2005, 10:03 AM
  5. oh me oh my hash maps up the wazoo
    By DarkDays in forum C++ Programming
    Replies: 5
    Last Post: 11-30-2001, 12:54 PM