C++: std::vector of function template pointers





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







0















The idea is to call similar Runge-Kutta function templates in a loop instead of doing it one by one. I've looked at similar solutions, I also tried void*, but was not able to apply to my problem due to conversion errors.



EDIT: these function templates are supposed to be used with fixed types, it's an overkill, but I would like to see whether there is an elegant solution.



Here is the full code:



#include <iostream>
#include <iomanip>
#include <cmath>
#include <functional>

template <typename X, typename F, typename H = double>
X runge_kutta1(const X &x, const F &f, H h)
{
return x + h * f(x);
}

template <typename X, typename F, typename H = double>
X runge_kutta2(const X &x, const F &f, H h)
{
X k1 = f(x);
return x + 0.5 * h * (k1 + f(x + h * k1));
}

struct pair
{
double v;
double w;

pair(double v, double w)
: v{v}, w{w}
{
}
};

inline pair operator*(double h, pair p)
{
return {h * p.v, h * p.w};
}

inline pair operator+(pair p1, pair p2)
{
return {p1.v + p2.v, p1.w + p2.w};
}

inline std::ostream &operator<<(std::ostream &stream, const pair &p)
{
stream << p.v << ", " << p.w;
return stream;
}

int main() {
{
double x = 0.0;
double x1 = 1.0;
double lambda = 2;
double h = 1.0E-3;
pair p{1.0 / lambda, 0.0};

const std::function<pair(pair)> cat =
[&lambda](const pair &p) { return pair{p.w, lambda * sqrt(1.0 + p.w * p.w)}; };
while (x + h < x1)
{
p = runge_kutta1(p, cat, h);
x = x + h;
}
p = runge_kutta1(p, cat, x1 - x);
pair expected = {cosh(lambda * x1) / lambda, sinh(lambda * x1)};
pair error = p + -1.0 * expected;

std::cout << std::setprecision(18) << "runge_kutta1:nFinal result: " << p << "n";
std::cout << "Error: " << error << "nn";
}

{
double x = 0.0;
double x1 = 1.0;
double lambda = 2;
double h = 1.0E-3;
pair p{1.0 / lambda, 0.0};

const std::function<pair(pair)> cat =
[&lambda](const pair &p) { return pair{p.w, lambda * sqrt(1.0 + p.w * p.w)}; };
while (x + h < x1)
{
p = runge_kutta2(p, cat, h);
x = x + h;
}
p = runge_kutta2(p, cat, x1 - x);
pair expected = {cosh(lambda * x1) / lambda, sinh(lambda * x1)};
pair error = p + -1.0 * expected;

std::cout << "runge_kutta2:nFinal result: " << p << "n";
std::cout << "Error: " << error << "n";
}
}


What I would like to have (the actual algorithm is simplified for the sake of readability):



std::vector<?> functions{runge_kutta1, runge_kutta2}; // two just as an example
double p = 1.0;
double h = 1.0E-3;
double lambda = 2;
const std::function<pair(pair)> cat =
[&lambda](const pair &p) { return pair{p.w, lambda * sqrt(1.0 + p.w * p.w)}; };
for (const auto& func : functions) {
double t = func(p, cat, h);
std::cout << t << "n";
}









share|improve this question

























  • Templates are not values. So your solution is the wrong path, it leads nowhere. You need to back up and reframe the problem, not try to solve it with a "vector of templates". Vectors store values, templates are not values.

    – Yakk - Adam Nevraumont
    Nov 16 '18 at 18:58











  • @Yakk-AdamNevraumont I'd rather say that template is not a type, rather than not a value - in my view, it makes it clearer. int is not a value, but vectors of ints do exist.

    – SergeyA
    Nov 16 '18 at 19:00













  • @Yakk-AdamNevraumont, I've got that, is there a way to somehow instantiate a template and use it inside std::vector? At least in this problem, where all the instances will have the same types.

    – Mikhail Krassavin
    Nov 16 '18 at 19:01








  • 1





    And honestly, there is no need to mention Runge-Kutta at all. Your goal is to call a set of template functions in some sort of containerized manner. No need to show us mathematical calculations to simply state this.

    – PaulMcKenzie
    Nov 16 '18 at 19:02











  • @MikhailKrassavin certainly, but it will be pointing to a specific version of it. It will only work with specified argument types.

    – SergeyA
    Nov 16 '18 at 19:02


















0















The idea is to call similar Runge-Kutta function templates in a loop instead of doing it one by one. I've looked at similar solutions, I also tried void*, but was not able to apply to my problem due to conversion errors.



EDIT: these function templates are supposed to be used with fixed types, it's an overkill, but I would like to see whether there is an elegant solution.



Here is the full code:



#include <iostream>
#include <iomanip>
#include <cmath>
#include <functional>

template <typename X, typename F, typename H = double>
X runge_kutta1(const X &x, const F &f, H h)
{
return x + h * f(x);
}

template <typename X, typename F, typename H = double>
X runge_kutta2(const X &x, const F &f, H h)
{
X k1 = f(x);
return x + 0.5 * h * (k1 + f(x + h * k1));
}

struct pair
{
double v;
double w;

pair(double v, double w)
: v{v}, w{w}
{
}
};

inline pair operator*(double h, pair p)
{
return {h * p.v, h * p.w};
}

inline pair operator+(pair p1, pair p2)
{
return {p1.v + p2.v, p1.w + p2.w};
}

inline std::ostream &operator<<(std::ostream &stream, const pair &p)
{
stream << p.v << ", " << p.w;
return stream;
}

int main() {
{
double x = 0.0;
double x1 = 1.0;
double lambda = 2;
double h = 1.0E-3;
pair p{1.0 / lambda, 0.0};

const std::function<pair(pair)> cat =
[&lambda](const pair &p) { return pair{p.w, lambda * sqrt(1.0 + p.w * p.w)}; };
while (x + h < x1)
{
p = runge_kutta1(p, cat, h);
x = x + h;
}
p = runge_kutta1(p, cat, x1 - x);
pair expected = {cosh(lambda * x1) / lambda, sinh(lambda * x1)};
pair error = p + -1.0 * expected;

std::cout << std::setprecision(18) << "runge_kutta1:nFinal result: " << p << "n";
std::cout << "Error: " << error << "nn";
}

{
double x = 0.0;
double x1 = 1.0;
double lambda = 2;
double h = 1.0E-3;
pair p{1.0 / lambda, 0.0};

const std::function<pair(pair)> cat =
[&lambda](const pair &p) { return pair{p.w, lambda * sqrt(1.0 + p.w * p.w)}; };
while (x + h < x1)
{
p = runge_kutta2(p, cat, h);
x = x + h;
}
p = runge_kutta2(p, cat, x1 - x);
pair expected = {cosh(lambda * x1) / lambda, sinh(lambda * x1)};
pair error = p + -1.0 * expected;

std::cout << "runge_kutta2:nFinal result: " << p << "n";
std::cout << "Error: " << error << "n";
}
}


What I would like to have (the actual algorithm is simplified for the sake of readability):



std::vector<?> functions{runge_kutta1, runge_kutta2}; // two just as an example
double p = 1.0;
double h = 1.0E-3;
double lambda = 2;
const std::function<pair(pair)> cat =
[&lambda](const pair &p) { return pair{p.w, lambda * sqrt(1.0 + p.w * p.w)}; };
for (const auto& func : functions) {
double t = func(p, cat, h);
std::cout << t << "n";
}









share|improve this question

























  • Templates are not values. So your solution is the wrong path, it leads nowhere. You need to back up and reframe the problem, not try to solve it with a "vector of templates". Vectors store values, templates are not values.

    – Yakk - Adam Nevraumont
    Nov 16 '18 at 18:58











  • @Yakk-AdamNevraumont I'd rather say that template is not a type, rather than not a value - in my view, it makes it clearer. int is not a value, but vectors of ints do exist.

    – SergeyA
    Nov 16 '18 at 19:00













  • @Yakk-AdamNevraumont, I've got that, is there a way to somehow instantiate a template and use it inside std::vector? At least in this problem, where all the instances will have the same types.

    – Mikhail Krassavin
    Nov 16 '18 at 19:01








  • 1





    And honestly, there is no need to mention Runge-Kutta at all. Your goal is to call a set of template functions in some sort of containerized manner. No need to show us mathematical calculations to simply state this.

    – PaulMcKenzie
    Nov 16 '18 at 19:02











  • @MikhailKrassavin certainly, but it will be pointing to a specific version of it. It will only work with specified argument types.

    – SergeyA
    Nov 16 '18 at 19:02














0












0








0








The idea is to call similar Runge-Kutta function templates in a loop instead of doing it one by one. I've looked at similar solutions, I also tried void*, but was not able to apply to my problem due to conversion errors.



EDIT: these function templates are supposed to be used with fixed types, it's an overkill, but I would like to see whether there is an elegant solution.



Here is the full code:



#include <iostream>
#include <iomanip>
#include <cmath>
#include <functional>

template <typename X, typename F, typename H = double>
X runge_kutta1(const X &x, const F &f, H h)
{
return x + h * f(x);
}

template <typename X, typename F, typename H = double>
X runge_kutta2(const X &x, const F &f, H h)
{
X k1 = f(x);
return x + 0.5 * h * (k1 + f(x + h * k1));
}

struct pair
{
double v;
double w;

pair(double v, double w)
: v{v}, w{w}
{
}
};

inline pair operator*(double h, pair p)
{
return {h * p.v, h * p.w};
}

inline pair operator+(pair p1, pair p2)
{
return {p1.v + p2.v, p1.w + p2.w};
}

inline std::ostream &operator<<(std::ostream &stream, const pair &p)
{
stream << p.v << ", " << p.w;
return stream;
}

int main() {
{
double x = 0.0;
double x1 = 1.0;
double lambda = 2;
double h = 1.0E-3;
pair p{1.0 / lambda, 0.0};

const std::function<pair(pair)> cat =
[&lambda](const pair &p) { return pair{p.w, lambda * sqrt(1.0 + p.w * p.w)}; };
while (x + h < x1)
{
p = runge_kutta1(p, cat, h);
x = x + h;
}
p = runge_kutta1(p, cat, x1 - x);
pair expected = {cosh(lambda * x1) / lambda, sinh(lambda * x1)};
pair error = p + -1.0 * expected;

std::cout << std::setprecision(18) << "runge_kutta1:nFinal result: " << p << "n";
std::cout << "Error: " << error << "nn";
}

{
double x = 0.0;
double x1 = 1.0;
double lambda = 2;
double h = 1.0E-3;
pair p{1.0 / lambda, 0.0};

const std::function<pair(pair)> cat =
[&lambda](const pair &p) { return pair{p.w, lambda * sqrt(1.0 + p.w * p.w)}; };
while (x + h < x1)
{
p = runge_kutta2(p, cat, h);
x = x + h;
}
p = runge_kutta2(p, cat, x1 - x);
pair expected = {cosh(lambda * x1) / lambda, sinh(lambda * x1)};
pair error = p + -1.0 * expected;

std::cout << "runge_kutta2:nFinal result: " << p << "n";
std::cout << "Error: " << error << "n";
}
}


What I would like to have (the actual algorithm is simplified for the sake of readability):



std::vector<?> functions{runge_kutta1, runge_kutta2}; // two just as an example
double p = 1.0;
double h = 1.0E-3;
double lambda = 2;
const std::function<pair(pair)> cat =
[&lambda](const pair &p) { return pair{p.w, lambda * sqrt(1.0 + p.w * p.w)}; };
for (const auto& func : functions) {
double t = func(p, cat, h);
std::cout << t << "n";
}









share|improve this question
















The idea is to call similar Runge-Kutta function templates in a loop instead of doing it one by one. I've looked at similar solutions, I also tried void*, but was not able to apply to my problem due to conversion errors.



EDIT: these function templates are supposed to be used with fixed types, it's an overkill, but I would like to see whether there is an elegant solution.



Here is the full code:



#include <iostream>
#include <iomanip>
#include <cmath>
#include <functional>

template <typename X, typename F, typename H = double>
X runge_kutta1(const X &x, const F &f, H h)
{
return x + h * f(x);
}

template <typename X, typename F, typename H = double>
X runge_kutta2(const X &x, const F &f, H h)
{
X k1 = f(x);
return x + 0.5 * h * (k1 + f(x + h * k1));
}

struct pair
{
double v;
double w;

pair(double v, double w)
: v{v}, w{w}
{
}
};

inline pair operator*(double h, pair p)
{
return {h * p.v, h * p.w};
}

inline pair operator+(pair p1, pair p2)
{
return {p1.v + p2.v, p1.w + p2.w};
}

inline std::ostream &operator<<(std::ostream &stream, const pair &p)
{
stream << p.v << ", " << p.w;
return stream;
}

int main() {
{
double x = 0.0;
double x1 = 1.0;
double lambda = 2;
double h = 1.0E-3;
pair p{1.0 / lambda, 0.0};

const std::function<pair(pair)> cat =
[&lambda](const pair &p) { return pair{p.w, lambda * sqrt(1.0 + p.w * p.w)}; };
while (x + h < x1)
{
p = runge_kutta1(p, cat, h);
x = x + h;
}
p = runge_kutta1(p, cat, x1 - x);
pair expected = {cosh(lambda * x1) / lambda, sinh(lambda * x1)};
pair error = p + -1.0 * expected;

std::cout << std::setprecision(18) << "runge_kutta1:nFinal result: " << p << "n";
std::cout << "Error: " << error << "nn";
}

{
double x = 0.0;
double x1 = 1.0;
double lambda = 2;
double h = 1.0E-3;
pair p{1.0 / lambda, 0.0};

const std::function<pair(pair)> cat =
[&lambda](const pair &p) { return pair{p.w, lambda * sqrt(1.0 + p.w * p.w)}; };
while (x + h < x1)
{
p = runge_kutta2(p, cat, h);
x = x + h;
}
p = runge_kutta2(p, cat, x1 - x);
pair expected = {cosh(lambda * x1) / lambda, sinh(lambda * x1)};
pair error = p + -1.0 * expected;

std::cout << "runge_kutta2:nFinal result: " << p << "n";
std::cout << "Error: " << error << "n";
}
}


What I would like to have (the actual algorithm is simplified for the sake of readability):



std::vector<?> functions{runge_kutta1, runge_kutta2}; // two just as an example
double p = 1.0;
double h = 1.0E-3;
double lambda = 2;
const std::function<pair(pair)> cat =
[&lambda](const pair &p) { return pair{p.w, lambda * sqrt(1.0 + p.w * p.w)}; };
for (const auto& func : functions) {
double t = func(p, cat, h);
std::cout << t << "n";
}






c++ templates






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 16 '18 at 19:20







Mikhail Krassavin

















asked Nov 16 '18 at 18:51









Mikhail KrassavinMikhail Krassavin

2818




2818













  • Templates are not values. So your solution is the wrong path, it leads nowhere. You need to back up and reframe the problem, not try to solve it with a "vector of templates". Vectors store values, templates are not values.

    – Yakk - Adam Nevraumont
    Nov 16 '18 at 18:58











  • @Yakk-AdamNevraumont I'd rather say that template is not a type, rather than not a value - in my view, it makes it clearer. int is not a value, but vectors of ints do exist.

    – SergeyA
    Nov 16 '18 at 19:00













  • @Yakk-AdamNevraumont, I've got that, is there a way to somehow instantiate a template and use it inside std::vector? At least in this problem, where all the instances will have the same types.

    – Mikhail Krassavin
    Nov 16 '18 at 19:01








  • 1





    And honestly, there is no need to mention Runge-Kutta at all. Your goal is to call a set of template functions in some sort of containerized manner. No need to show us mathematical calculations to simply state this.

    – PaulMcKenzie
    Nov 16 '18 at 19:02











  • @MikhailKrassavin certainly, but it will be pointing to a specific version of it. It will only work with specified argument types.

    – SergeyA
    Nov 16 '18 at 19:02



















  • Templates are not values. So your solution is the wrong path, it leads nowhere. You need to back up and reframe the problem, not try to solve it with a "vector of templates". Vectors store values, templates are not values.

    – Yakk - Adam Nevraumont
    Nov 16 '18 at 18:58











  • @Yakk-AdamNevraumont I'd rather say that template is not a type, rather than not a value - in my view, it makes it clearer. int is not a value, but vectors of ints do exist.

    – SergeyA
    Nov 16 '18 at 19:00













  • @Yakk-AdamNevraumont, I've got that, is there a way to somehow instantiate a template and use it inside std::vector? At least in this problem, where all the instances will have the same types.

    – Mikhail Krassavin
    Nov 16 '18 at 19:01








  • 1





    And honestly, there is no need to mention Runge-Kutta at all. Your goal is to call a set of template functions in some sort of containerized manner. No need to show us mathematical calculations to simply state this.

    – PaulMcKenzie
    Nov 16 '18 at 19:02











  • @MikhailKrassavin certainly, but it will be pointing to a specific version of it. It will only work with specified argument types.

    – SergeyA
    Nov 16 '18 at 19:02

















Templates are not values. So your solution is the wrong path, it leads nowhere. You need to back up and reframe the problem, not try to solve it with a "vector of templates". Vectors store values, templates are not values.

– Yakk - Adam Nevraumont
Nov 16 '18 at 18:58





Templates are not values. So your solution is the wrong path, it leads nowhere. You need to back up and reframe the problem, not try to solve it with a "vector of templates". Vectors store values, templates are not values.

– Yakk - Adam Nevraumont
Nov 16 '18 at 18:58













@Yakk-AdamNevraumont I'd rather say that template is not a type, rather than not a value - in my view, it makes it clearer. int is not a value, but vectors of ints do exist.

– SergeyA
Nov 16 '18 at 19:00







@Yakk-AdamNevraumont I'd rather say that template is not a type, rather than not a value - in my view, it makes it clearer. int is not a value, but vectors of ints do exist.

– SergeyA
Nov 16 '18 at 19:00















@Yakk-AdamNevraumont, I've got that, is there a way to somehow instantiate a template and use it inside std::vector? At least in this problem, where all the instances will have the same types.

– Mikhail Krassavin
Nov 16 '18 at 19:01







@Yakk-AdamNevraumont, I've got that, is there a way to somehow instantiate a template and use it inside std::vector? At least in this problem, where all the instances will have the same types.

– Mikhail Krassavin
Nov 16 '18 at 19:01






1




1





And honestly, there is no need to mention Runge-Kutta at all. Your goal is to call a set of template functions in some sort of containerized manner. No need to show us mathematical calculations to simply state this.

– PaulMcKenzie
Nov 16 '18 at 19:02





And honestly, there is no need to mention Runge-Kutta at all. Your goal is to call a set of template functions in some sort of containerized manner. No need to show us mathematical calculations to simply state this.

– PaulMcKenzie
Nov 16 '18 at 19:02













@MikhailKrassavin certainly, but it will be pointing to a specific version of it. It will only work with specified argument types.

– SergeyA
Nov 16 '18 at 19:02





@MikhailKrassavin certainly, but it will be pointing to a specific version of it. It will only work with specified argument types.

– SergeyA
Nov 16 '18 at 19:02












1 Answer
1






active

oldest

votes


















2














You can not have a pointer to a function template. You can only have a pointer to specific instantiation of the template. In a same manner, you can't pack a template into std::function - only a specific instantiation of it.



And you can only put objects of the same type in the container - so your pointers will have to be of the same type (i.e. the function they point to should accept the same type of arguments and return the same type).



std::function will have the same limitation - all std::functions inside the container must be of the same type, in terms of return value and arguments.






share|improve this answer
























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53343772%2fc-stdvector-of-function-template-pointers%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    2














    You can not have a pointer to a function template. You can only have a pointer to specific instantiation of the template. In a same manner, you can't pack a template into std::function - only a specific instantiation of it.



    And you can only put objects of the same type in the container - so your pointers will have to be of the same type (i.e. the function they point to should accept the same type of arguments and return the same type).



    std::function will have the same limitation - all std::functions inside the container must be of the same type, in terms of return value and arguments.






    share|improve this answer




























      2














      You can not have a pointer to a function template. You can only have a pointer to specific instantiation of the template. In a same manner, you can't pack a template into std::function - only a specific instantiation of it.



      And you can only put objects of the same type in the container - so your pointers will have to be of the same type (i.e. the function they point to should accept the same type of arguments and return the same type).



      std::function will have the same limitation - all std::functions inside the container must be of the same type, in terms of return value and arguments.






      share|improve this answer


























        2












        2








        2







        You can not have a pointer to a function template. You can only have a pointer to specific instantiation of the template. In a same manner, you can't pack a template into std::function - only a specific instantiation of it.



        And you can only put objects of the same type in the container - so your pointers will have to be of the same type (i.e. the function they point to should accept the same type of arguments and return the same type).



        std::function will have the same limitation - all std::functions inside the container must be of the same type, in terms of return value and arguments.






        share|improve this answer













        You can not have a pointer to a function template. You can only have a pointer to specific instantiation of the template. In a same manner, you can't pack a template into std::function - only a specific instantiation of it.



        And you can only put objects of the same type in the container - so your pointers will have to be of the same type (i.e. the function they point to should accept the same type of arguments and return the same type).



        std::function will have the same limitation - all std::functions inside the container must be of the same type, in terms of return value and arguments.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 16 '18 at 18:57









        SergeyASergeyA

        45k53990




        45k53990
































            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53343772%2fc-stdvector-of-function-template-pointers%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Florida Star v. B. J. F.

            Danny Elfman

            Lugert, Oklahoma