是否可以在没有模板的情况下使用泛型编程?

Is it possible to use generic programming without templates?

举例来说,我有一个函数 returns 来自二维数组的值:

float get_2d_noise(const point& p)
{
    return map2D[p.x][p.y];
}

point 是我定义为我的图书馆的一部分的 class:

struct point
{
    int x;
    int y;
}

除了这样做:

template<typename T>
float get_2d_noise(const T& p)
{
    return noisemap[p.x][p.y];
}

有没有可能达到同样的效果?即,以任何具有 x 和 y 成员的方式创建 get_2d_noise ? (最好在编译时捕获错误,而不是运行时)。

一种可能性是在句法上明确说明您想做什么。您可以创建一个接口 IPoint 或类似接口(在 C++ 中可以使用抽象 class 来完成),您可以在其中为数据成员定义 getter,例如 GetXGetY;那么您可以按如下方式制定函数。

float get_2d_noise(const IPoint& p)
{
    return noisemap[p.GetX()][p.GetY()];
}

这样,您就不必使用泛型;相反,您将使用继承。但是,您想要与 get_2s_noise 一起使用的任何类型都必须从 IPoint 派生(并以有意义的方式实现 getter),但这似乎正是您要寻找的。

Is it possible to get the same effect? I.e., create get_2d_noise in such a way that anything with an x and y member will work? (preferably catching errors at compile time, rather than runtime).

这就是模板存在的全部意义所在:创建它们是为了支持 C++ 中的泛型编程。所以不,除了编写模板之外,没有其他方法可以用 C++ 编写模板。

您可以编写一个宏,将类型的名称作为参数,然后创建所需的函数。像

CREATE_2D_NOISE_FOR(someType)

扩展到

float get_2d_noise(const someType& p) {
    return noisemap[p.x][p.y];
}

但是,强烈不建议这样做,因为您会失去模板的所有表现力并获得宏带来的所有问题。

您可能会使用通用 lambda (c++14) 作弊,因此您不会显式使用 template:

auto get_2d_noise = [&](const auto& p) -> float
{
    return map2D[p.x][p.y];
};