Home How can you pass a function as a template parmater where the function return is same as the template parameter?
Reply: 3

How can you pass a function as a template parmater where the function return is same as the template parameter?

tenspd137
1#
tenspd137 Published in 2017-12-06 03:56:32Z

I am trying to figure out how I can make a template class that works like the following:

template<typename T, typename Fn>
class Point
{
public:
    T x;
    T y;

    void pt(const std::string& x_str, const std::string& y_str)
    {
          x = Fn(x_str);
          y = Fn(y_str);
    }
    .... more Point stuff ....
};

typedef Point<float, std::stof> FPoint;
typedef Point<int, std::stoi> IPoint;
.....

and then when I read a string - say "100.25,200.25", I could split on "," (which I actually have figured out how to do, and then say, set that point:

FPoint a;
a.pt("100.25","200.25")

so far I have tried defining directly as I have above, I have tried:

template<typename T, T (C*)(const std::string&)>
.....

and

template<typename T, T Fn(const std::string&)>
......

and then doing: typedef Point FloatPoint;

and I get various errors like cannot convert from 'overloaded-function' to 'float (__cdecl *)(const std::string &)'or 'std::stof' is not a valid template type argument for parameter 'convert_func' depending on how I try to define the parameter. Any hints - nothing I have googled has seemed to help.

Thanks!

R Sahu
2#
R Sahu Reply to 2017-12-06 04:55:17Z

You cannot use

typedef Point<float, std::stof> FPoint;

since std::stof is a pointer to a function, not a type.

You could try changing the template parameter to a non-type parameter, such as:

template<typename T, T(*Fn)(const std::string&)>
class Point { ... };

but that won't work since std::stof has an optional parameter of type std::size_t*. The type of std::stof, that takes a std::string const& as the first parameter is float (*)(std::string const&, std::size_t*).

If you try to shoehorn Point to match that declaration,

template<typename T, T(*Fn)(const std::string&, std::size_t*)>
class Point { ... };

you won't be able to use:

typedef Point<int, std::stoi> IPoint;

since std::stoi has a third parameter, int base. The type of std::stoi is int (*)(std::string const&, std::size_t*, int).

I think your best option is to create two wrapper functions in your namespace and use them instead of using std::stof and std::stoi directly as template parameters.

The following demonstrative program works in my setup.

#include <cstdlib>
#include <string>
#include <functional>

template<typename T, T(*Fn)(const std::string&)>
class Point
{
public:
    T x;
    T y;

    void pt(const std::string& x_str, const std::string& y_str)
    {
       x = Fn(x_str);
       y = Fn(y_str);
    }
};

namespace MyApp
{
   float stof(std::string const& in)
   {
      return std::stof(in);
   }

   int stoi(std::string const& in)
   {
      return std::stoi(in);
   }
}

typedef Point<float, MyApp::stof> FPoint;
typedef Point<int, MyApp::stoi> IPoint;

int main()
{
   FPoint a;
   a.pt("100.25", "200.25");
   IPoint b;
   b.pt("100", "200");
}
tenspd137
3#
tenspd137 Reply to 2017-12-06 04:08:55Z

I think I figured it out - std::stof is actually std::stof(const string&, size_t*). I put that in the template parameter (T (C*)(const std::string&, size_t*) and now I get errors in paces where I use Point as not having enough parameters. After I fix that up, if I am still wrong, I'll come back and remove this answer.

SoronelHaetir
4#
SoronelHaetir Reply to 2017-12-06 04:10:20Z

Make the second parameter be a function pointer: template class Point {};

Note that neither std::stof or std::stoi would be valid arguments for that template (they both take additional arguments), but it would be fairly easy to create wrappers that rely on the default parameters (the template argument has to match types exactly, while the call does not): typedef Point fPoint;

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.30827 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO