如何将函数作为模板参数传递,其中函数返回与模板参数相同?

时间:2017-12-06 03:56:32

标签: c++ templates function-pointers

我试图弄清楚如何制作一个类似于以下内容的模板类​​:

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;
.....

然后当我读到一个字符串 - 说&#34; 100.25,200.25&#34;时,我可以分开&#34;,&#34; (我实际上已经想出了怎么做,然后说,设定这一点:

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

到目前为止,我已尝试直接定义,如上所述,我尝试过:

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

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

然后做:     typedef Point FloatPoint;

我收到了各种错误,例如无法转换为“超载功能”#39; to&#39; float(__ cdecl *)(const std :: string&amp;)&#39;或&#39; std :: stof&#39;不是参数&#39; convert_func&#39;的有效模板类型参数。取决于我如何尝试定义参数。任何提示 - 我没有用Google搜索,似乎有所帮助。

谢谢!

3 个答案:

答案 0 :(得分:1)

你不能使用

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

因为std::stof是指向函数的指针,而不是类型。

您可以尝试将模板参数更改为非类型参数,例如:

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

但由于std::stof具有std::size_t*类型的可选参数,因此无效。将std::stof作为第一个参数的std::string const&类型为float (*)(std::string const&, std::size_t*)

如果你试图将Point鞋拔,以匹配该声明,

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

你将无法使用:

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

因为std::stoi有第三个参数int basestd::stoi的类型为int (*)(std::string const&, std::size_t*, int)

我认为您最好的选择是在命名空间中创建两个包装函数并使用它们,而不是直接使用std::stofstd::stoi作为模板参数。

以下演示程序适用于我的设置。

#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");
}

答案 1 :(得分:0)

我想我想出来了 - std :: stof实际上是std :: stof(const string&amp;,size_t *)。我把它放在模板参数(T(C *)(const std :: string&amp;,size_t *)中,现在我得到的错误是我使用Point没有足够的参数。在我解决之后,如果我是还是错了,我会回来删除这个答案。

答案 2 :(得分:0)

使第二个参数成为函数指针: 模板 class Point {};

请注意,std :: stof或std :: stoi都不是该模板的有效参数(它们都采用其他参数),但是创建依赖于默认参数的包装器(模板参数具有参数)相当容易完全匹配类型,而调用没有): typedef Point fPoint;