C++/CLI 中的函数模板
Function templates in C++/CLI
我正在尝试在 C++/CLI 的命名空间中编写一些函数模板,如下所示:
// header file
namespace MyCLI {
namespace MyFunctions {
template <typename T>
double sum(T a, T b) {
return (double) a + b;
}
}
}
第一个问题是,当我将项目编译成一个 dll 并尝试使用它时,命名空间 MyFunctions 没有出现。我认为这是因为我没有为我需要的所有类型显式实例化我的模板,所以我在头文件的底部添加以下内容:
extern template double MyCLI::MyFunctions::sum<double>(double,double);
但这仍然无法让我访问 double
类型的函数 sum
。我怀疑,由于项目被编译成托管代码,这遵循了 C# 的规则,即没有 class 就不能拥有函数。所以接下来我尝试在命名空间 MyCLI 中创建一个 class 并使 sum
成为 class 的静态成员,如下所示:
// header file
namespace MyCLI {
public ref class MyFunctions
{
public:
template <typename T>
static double sum(T a, T b) {
return (double) a + b;
}
};
}
extern template double MyCLI::MyFunctions::sum<double>(double,double);
现在,当我使用程序集时,我可以在 MyCLI
中看到 MyFunctions
class,但我仍然无法从 class 中访问 sum
函数.
如果有人能给我任何关于如何解决这个问题的建议,或者为什么我一开始就遇到这个问题,我将不胜感激。
这不是显式实例化模板的正确语法。您需要删除 extern
关键字并将实例化放在 cpp 文件中(而不是 header 中),因此它只定义一次。您无法看到该方法,因为它不存在 由于缺少模板实例化。模板不是泛型,它们看起来很相似但有很大不同。模板在编译时实例化,而泛型在运行时具体化。
但是,如果您计划从不同的 .NET 语言使用此代码,那您就倒霉了:该方法的名称字面上包含尖括号,因此您如果不违反语言的命名规则,你将很难使用它。您可以使用反射,但我确定这不是您想要的。
对于这种简单的情况,您可以简单地编写几个重载(根本不使用模板),这是最简单的事情。如果您想要更多花哨的东西,请参阅 my answer here 获取灵感。
我正在尝试在 C++/CLI 的命名空间中编写一些函数模板,如下所示:
// header file
namespace MyCLI {
namespace MyFunctions {
template <typename T>
double sum(T a, T b) {
return (double) a + b;
}
}
}
第一个问题是,当我将项目编译成一个 dll 并尝试使用它时,命名空间 MyFunctions 没有出现。我认为这是因为我没有为我需要的所有类型显式实例化我的模板,所以我在头文件的底部添加以下内容:
extern template double MyCLI::MyFunctions::sum<double>(double,double);
但这仍然无法让我访问 double
类型的函数 sum
。我怀疑,由于项目被编译成托管代码,这遵循了 C# 的规则,即没有 class 就不能拥有函数。所以接下来我尝试在命名空间 MyCLI 中创建一个 class 并使 sum
成为 class 的静态成员,如下所示:
// header file
namespace MyCLI {
public ref class MyFunctions
{
public:
template <typename T>
static double sum(T a, T b) {
return (double) a + b;
}
};
}
extern template double MyCLI::MyFunctions::sum<double>(double,double);
现在,当我使用程序集时,我可以在 MyCLI
中看到 MyFunctions
class,但我仍然无法从 class 中访问 sum
函数.
如果有人能给我任何关于如何解决这个问题的建议,或者为什么我一开始就遇到这个问题,我将不胜感激。
这不是显式实例化模板的正确语法。您需要删除 extern
关键字并将实例化放在 cpp 文件中(而不是 header 中),因此它只定义一次。您无法看到该方法,因为它不存在 由于缺少模板实例化。模板不是泛型,它们看起来很相似但有很大不同。模板在编译时实例化,而泛型在运行时具体化。
但是,如果您计划从不同的 .NET 语言使用此代码,那您就倒霉了:该方法的名称字面上包含尖括号,因此您如果不违反语言的命名规则,你将很难使用它。您可以使用反射,但我确定这不是您想要的。
对于这种简单的情况,您可以简单地编写几个重载(根本不使用模板),这是最简单的事情。如果您想要更多花哨的东西,请参阅 my answer here 获取灵感。