Thread: Pointer to template function workaround

  1. #1
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607

    Pointer to template function workaround

    Since pointers to template functions are not possible in C++ I would like to know how to go about solving the following issue:

    Given the template function:

    Code:
    namespace Math
    {
        class Utils
        {
              template <typename T> static T LinearInterpolate(T value1, T value2, float lerpFactor)
              {
                     return static_cast<T>(value1 + lerpFactor * (value2 - value1));
              }
        }
    }
    To use this function you obviously do:

    Code:
    float floatResult = Math.Utils.LinearInterpolate<float>(10.0f,20.0f,0.5f);
    double doubleResult = Math.Utils.LinearInterpolate<double>(10.0,20.0,5.0f);
    D3DXCOLOR colorResult = Math.Utils.LinearInterpolate<D3DXCOLOR>(D3DXCOLOR(0.0f, 0.0f, 0.0f, 0.0f), D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f), 0.5f);
    However this will be littered throughout my code. If I want to change the type of linear interpolation (IE: cosine interpolation) using this approach I will have to go through the code and change all LinearInterpolate calls to some other template function. However it is nice to have a template function here b/c you can then LinearInterpolate between any type that has the correct operators overloaded which is quite handy.

    It would be nice to simply use a function pointer to Math.Utils.LinearInterpolate which then would mean to alter the function being used I would simply alter what function the pointer pointed to...but b/c it is a template this is not an option.

    Any ideas?

    EDIT: Fixed typo in code that used coef instead of lerpFactor.
    Last edited by VirtualAce; 01-13-2012 at 02:15 AM.

  2. #2
    Novice
    Join Date
    Jul 2009
    Posts
    568
    Maybe make this policy-based?

    Code:
    template<typename T> class Linear
    {
    public:
            T interpolate(T value1, T value2, float lerpFactor)
            {
                    return (value1 + coef * (value2 - value1));
            }
    };
    
    template<typename T> class Cosine
    {
    public:
            T interpolate(T value1, T value2, float lerpFactor)
            {
                    // consine interpolation implementation
            }
    };
    
    
    // Change default parameter to `Cosine<T>` if you want to change everywhere.
    template <typename T, class C = Linear<T> >
    static T Interpolate(T value1, T value2, float lerpFactor)
    {
            return static_cast<T>C::interpolate(value1, value2, lerpFactor);
    }
    
    float floatResult = Interpolate<float>(10.0f, 20.0f, 0.5f);
    Not completely sure if this is what your looking for, but I gave it a shot.
    Last edited by msh; 01-13-2012 at 12:56 AM.
    Disclaimer: This post shows my ignorance at the time of its making. I claim ownership of but not responsibility for all errors in it. Reference at your own peril.

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by VirtualAce
    To use this function you obviously do:
    Heh, I think you have been dabbling in another programming language recently

    Quote Originally Posted by VirtualAce
    However this will be littered throughout my code. If I want to change the type of linear interpolation (IE: cosine interpolation) using this approach I will have to go through the code and change all LinearInterpolate calls to some other template function. However it is nice to have a template function here b/c you can then LinearInterpolate between any type that has the correct operators overloaded which is quite handy.
    Why not just define:
    Code:
    template <typename T>
    T interpolate(T value1, T value2, float lerpFactor)
    {
        return Math::Utils::LinearInterpolate<T>(value1, value2, lerpFactor);
    }
    Then use interpolate instead of the specific function template. So, if you need to change the interpolation function, just change this one function template.

    Quote Originally Posted by msh
    Maybe make this policy-based?
    I was going down that path too, but the benefits provided are a little different from what I think VirtualAce is asking for.
    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

  4. #4
    Novice
    Join Date
    Jul 2009
    Posts
    568
    Quote Originally Posted by laserlight View Post
    I was going down that path too, but the benefits provided are a little different from what I think VirtualAce is asking for.
    I figured that he could want to use either.
    Disclaimer: This post shows my ignorance at the time of its making. I claim ownership of but not responsibility for all errors in it. Reference at your own peril.

  5. #5
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Then use interpolate instead of the specific function template. So, if you need to change the interpolation function, just change this one function template.
    Very nice - one more level of abstraction is all I needed. The policy thing is pretty nifty as well but probably a bit too much for this simple task. Thank you both for your suggestions.

    And yes...I have been dabbling in another language recently. I guess my use of the dot operator sort of makes that obvious.

  6. #6
    Novice
    Join Date
    Jul 2009
    Posts
    568
    "All problems in computer science can be solved by another level of abstraction... except for the problem of too many layers of abstraction."
    Disclaimer: This post shows my ignorance at the time of its making. I claim ownership of but not responsibility for all errors in it. Reference at your own peril.

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    If you would want a pointer to the function, you might as well take a functor into the function.
    A lambda that wraps the appropriate interpolation function or std::bind or boost::bind would be enough to create an appropriate functor object.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Is it critical that the polymorphism be static? If you tolerate dynamic, you can have your pointer..

    Code:
    template <typename T>
    class InterpolateInterface
    {
        virtual ~InterpolateInterface() {}
        virtual T Interpolate(T a, T b, T frac) = 0;
    };
    
    template <typename T>
    class LinearInterpolate : public InterpolateInterface<T>
    {
    public:
        T Interpolate(T a, T b, T frac) { return b*frac + a*(T(1)-frac); }
    };
    
    InterpolateInterface<float> *pMyInterpolator = new LinearInterpolate<float>;
    EDIT: Won't you need to change the code anyway if you switch from linear to (for example) cosine? The interpolation parameter is likely not the same so you need to change it anyway.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  9. #9
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Another great suggestion. I went the interface route at first but then did not like the fact that I had to dynamically allocate the object. It seemed like a waste when the object was doing so little.

    All are definitely valid approaches and I will look at each one. Thanks for the help.

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Well, to tweak brewbuck's solution a little, you could a reference to the base class. Then there will be no need for any new'ing.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 3
    Last Post: 01-30-2011, 04:28 PM
  2. template parameter on a function that dont use the template
    By underthesun in forum C++ Programming
    Replies: 1
    Last Post: 06-22-2009, 05:38 PM
  3. Specialising a member function with a template template parameter
    By the4thamigo_uk in forum C++ Programming
    Replies: 10
    Last Post: 10-12-2007, 04:37 AM
  4. Replies: 4
    Last Post: 09-07-2006, 01:32 AM
  5. Template Friend Workaround for MSVC?
    By LuckY in forum C++ Programming
    Replies: 1
    Last Post: 04-01-2005, 05:41 PM