Thread: Help with template data type argument

  1. #1
    Algorithm engineer
    Join Date
    Jun 2006
    Posts
    286

    Help with template data type argument

    Hi!

    I am writing an image handling program, and have implemented the image class as a template class, to be able to choose more freely which data type I want the channels to be represented with.

    So I have my template class
    Code:
    template <class T, uint NUM_CHANNELS>
    class mp_image {
    public:
        static const size_t BPP = NUM_CHANNELS * sizeof(T); /* Bytes per pixel */
        void *pixels;
        uint width;
        uint height;
        uint pitch; /* pitch = number of bytes per line */
        
        /* constructor */
        mp_image(uint w, uint h);
        /* destructor */
        ~mp_image();
    };
    Now comes the tricky part. I have declared a member function externally in another header file (this is a bluring function and I want every 'filter', and other manipulating function to be declared outside of the class declaration), it looks like this:

    Code:
    template<class T, uint NC, class T2>
    mp_image<T, NC>::SquareBlur<T2>(uint radius);
    I must have written something wrong, since the compile complains: expected constructor, destructor, or type conversion before '<' token. And it means the last of the '<' tokens, the one just before T2. Do you know how it should be?

    Anyway, this is not the biggest problem. I need to have a second data type T2 for this function, since it needs a data type with the same precision as T, but one which is able to store values about the-number-of-pixels-in-the-picture times as high, because of the way the algorithm works. So, at least 20 - 24 bits more, a uint8 for example would preferably mean to send a uint32 as T2, and a float would mean a double. Now, is there any way to determine T2 automatically instead of having to provide it in each call, so that I could just type myImage.SquareBlur(rad) for example and it would figure out the type of T2 itself? Is it possible to create a lookup table where both the keys and the values are data types?
    Come on, you can do it! b( ~_')

  2. #2
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> mp_image<T, NC>::SquareBlur<T2>(uint radius);
    I don't think you want the :: there, do you?

    >> is there any way to determine T2 automatically instead of having to provide it in each call
    Maybe, although I would provide the function that let's the caller specify the type and then provide a second version that let's you figure it out (and then calls the three template argument version).

    To figure out what type to use, you can try to use the values in numeric_limits. If you want to restrict which data types can be sent to that function, you can also create a helper class that uses template meta-programming to return the proper type. I would have to spend some time on it to get the syntax correct, but here is the basic idea:
    Code:
    template <typename T>
    struct TypeConverter
    {
      // Something should be added here that causes an error if this is instantiated or used,
      // perhaps just leaving the next line commented out will work:
      // typedef int BiggerType;
    };
    
    struct TypeConverter<uint8_t>
    {
      typedef uint32 BiggerType;
    };
    
    struct TypeConverter<float>
    {
      typedef double BiggerType;
    };
    
    // ... etc. for all allowed types
    
    template<class T, uint NC, class T2>
    mp_image<T, NC> SquareBlur<T2>(uint radius); // implemented elsewhere
    
    template<class T, uint NC>
    mp_image<T, NC> SquareBlur(uint radius)
    {
      return SquareBlur<T, NC, typename TypeConverter<T>::BiggerType>(radius);
    }
    If the user wants an unsupported type they have to call the three template version directly.

  3. #3
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    But the <T2> doesn't belong in the prototype either.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  4. #4
    Algorithm engineer
    Join Date
    Jun 2006
    Posts
    286
    Daved, isn't the function you declared just a normal function (not a member function) which returns an mp_image<T, NC>? I want SquareBlur to be a member of the class. Isn't that what the :: does? I just realized since my version with void didn't work, but your version without void works.
    Come on, you can do it! b( ~_')

  5. #5
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Sorry, I looked to see if you ever mentioned that you wanted it to be a member function, but couldn't find it (I see it now). If you want it to be a member function, don't you have to declare it in the class itself?

    And yes, you should add void since otherwise there is no return type.

    >> But the <T2> doesn't belong in the prototype either.
    Do you mean
    Code:
    template<class T, uint NC, class T2>
    mp_image<T, NC> SquareBlur<T2>(uint radius); // implemented elsewhere
    should be
    Code:
    template<class T, uint NC, class T2>
    mp_image<T, NC> SquareBlur(uint radius); // implemented elsewhere
    ?

    Aren't there any other errors with that example (that needs to be changed anyway since it is supposed to be a member function)?

  6. #6
    Algorithm engineer
    Join Date
    Jun 2006
    Posts
    286
    Is there some way in which I can derive a template class from numeric_limits?
    Come on, you can do it! b( ~_')

  7. #7
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> If you want it to be a member function, don't you have to declare it in the class itself?
    For some older compilers, yes - but not a language requirement.

    >> But the <T2> doesn't belong in the prototype either.
    In other words, here's how you do a templated member function of a template class:
    Code:
    template<typename T>
    struct X
    {
       template<typename U>
       void foo(const U &u);
    };
    
    template<typename T> 
    template<typename U>
    void X<T>::foo(const U &u)
    {
    }
    Notice foo doesn't have "<U>" on it. I still have to lookup the syntax on MSDN myself from time to time

    >> Aren't there any other errors with that example
    Yeah, he's missing a return type. Which probably caused the confusion in thinking "mp_image<T,NC>" was the return type

    >> Is there some way in which I can derive a template class from numeric_limits?
    Well, let us see the "TypeConverter" you're working on. There's probably a better way to accomplish your goal than deriving from numeric_limits.

    gg

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. xor linked list
    By adramalech in forum C Programming
    Replies: 23
    Last Post: 10-14-2008, 10:13 AM
  2. Code review
    By Elysia in forum C++ Programming
    Replies: 71
    Last Post: 05-13-2008, 09:42 PM
  3. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  4. Using VC Toolkit 2003
    By Noobwaker in forum Windows Programming
    Replies: 8
    Last Post: 03-13-2006, 07:33 AM
  5. Errors
    By Rhidian in forum C Programming
    Replies: 10
    Last Post: 04-04-2005, 12:22 PM