在函数 return 与模板参数相同的情况下,如何将函数作为模板参数传递?

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

我正在想办法制作一个模板 class,其工作原理如下:

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

然后当我读取一个字符串时 - 说“100.25,200.25”,我可以拆分“,”(我实际上已经想出了如何做,然后说,设置那个点:

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;

并且出现各种错误,例如无法从 'overloaded-function' 转换为 'float (__cdecl *)(const std::string &)' 或 'std::stof' is not a valid参数 'convert_func' 的模板类型参数取决于我尝试定义参数的方式。任何提示 - 我用谷歌搜索的任何内容似乎都没有帮助。

谢谢!

我想我明白了 - std::stof 实际上是 std::stof(const string&, size_t*)。我把它放在模板参数 (T (C*)(const std::string&, size_t*) 中,现在我在使用 Point 的地方出现错误,因为没有足够的参数。在我修复之后up,如果我还是错了,我会回来删除这个答案。

将第二个参数设为函数指针: 模板 class 点 {};

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

您不能使用

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

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

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

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

但这行不通,因为 std::stof 有一个类型为 std::size_t* 的可选参数。以std::string const&作为第一个参数的std::stof的类型是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");
}