c++templatesnon-member-functions

How do you call a non-member function with a template in c++, where the typename is only in the return?


My goal is to have a non member function use a template for a return value. This is so I can return a float array, a double array, etc. I get a "couldn't deduce template parameter 'T'" error.

Here is the method I am trying to use:

template<typename T>
T* make(double magnitude, double frequency, double radians, double seconds,
        int samplesPerSecond) {
    long samples = length(seconds, samplesPerSecond);
    T *wave = new T[samples];
    for (int i = 0; i < samples; i++) {
        wave[i] = magnitude
                * sin(
                        (2.0 * (M_PI) * frequency * i / samplesPerSecond)
                                + radians);
    }
    return wave;
}

I first tried to call the method normally.

double *ds = make(magnitude, frequency, radians, seconds, samplesPerSecond);

I have tried adding the typename after the function name.

double *ds = make<double>(magnitude, frequency, radians, seconds, samplesPerSecond);

I looked over several pages on the web and they have all covered member functions so far and explained that the type cannot be deduced from a return type, so how do you tell the compiler the type?


Solution

  • You can very much do this with non-member functions, as per the following example, which adds together two values of a templated type:

    #include <iostream>
    
    template<typename T> T add(const T &val1, const T &val2) {
        return val1 + val2;
    }
    
    int main() {
        auto eleven = add<int>(4, 7);
        std::cout << "4   + 7   = " << eleven << '\n';
        auto threePointFour = add<double>(1.1, 2.3);
        std::cout << "1.1 + 2.3 =  " << threePointFour << '\n';
    }
    

    The output of that code is, as expected:

    4   + 7   = 11
    1.1 + 2.3 =  3.4
    

    It's possible that your case isn't working because the definition of the templated function may be incorrect - since you haven't supplied that, it's hard to tell for sure. Hence you may want to see how it compares to my own add function as shown above.


    As an aside (since your heading indicates this may be what you're attempting), you can also do this without using the templated types in the parameter list (only the return type):

    #include <iostream>
    
    template<typename T> T addAndHalve(const double &val1, const double &val2) {
        auto x = (val1 + val2) / 2;
        std::cout << "debug " << x << ": ";
        return x;
    }
    
    int main() {
        auto eleven = addAndHalve<int>(4, 7);
        std::cout << "(4   + 7  ) / 2 = " << eleven << '\n';
        auto threePointFour = addAndHalve<double>(1.1, 2.3);
        std::cout << "(1.1 + 2.3) / 2 =  " << threePointFour << '\n';
    }
    

    You can see this only affects the return value, using double for all parameters:

    debug 5.5: (4   + 7  ) / 2 = 5
    debug 1.7: (1.1 + 2.3) / 2 =  1.7