C++泛型编程之参数模板

157 阅读2分钟

一、C++ 模板

1.1 简单的类模板声明

1.1.1 示例

其中 T 是模板参数

template <typename T>
class MyContainer
{
public:
    // ...
private:
    T data;
};

1.1.2 调用

首先完善一下 MyContainer 类,在类模板中,可以像普通类一样声明成员函数,只不过这些成员函数应该使用类模板中定义的类型参数 T

template<typename T>
class MyContainer {
public:
    void setData(T data) {
        m_data = data;
    }

    T getData() const {
        return m_data;
    }

private:
    T m_data;
};

可以通过将 T 替换为实际的类型来创建该类的实例,具体的调用示例如下所示:

int main()
{
    // 创建一个包装 int 类型的 MyContainer 实例
    MyContainer<int> myIntContainer;
    myIntContainer.setData(42);
    std::cout << myIntContainer.getData() << std::endl;

    // 创建一个包装 double 类型的 MyContainer 实例
    MyContainer<double> myDoubleContainer;
    myDoubleContainer.setData(3.14);
    std::cout << myDoubleContainer.getData() << std::endl;

    return 0;
}

在这个例子中,我们创建了两个不同的 MyContainer 实例,分别包装了 intdouble 类型的数据。在创建实例时,需要将 T 替换为实际的类型,例如将 T 替换为 int ,就可以创建一个 MyContainer<int> 类型的实例。

在实例化 MyContainer 之后,我们可以使用该实例的成员函数 setDatagetData 来设置和获取其内部的数据,这些成员函数不会受到包装数据类型的影响,可以在不同类型的 MyContainer 实例上调用。

1.2 简单的函数模板声明

1.2.1 示例

其中 TU 是模板参数

template <typename T, typename U>
T add(T a, U b)
{
    return a + b;
}

1.2.2 调用

可以像普通函数一样调用该函数模板,只需要在函数名后面使用尖括号 < > 括起模板参数即可。例如:

int main()
{
    int a = 1;
    double b = 2.5;
    // 调用 add 函数模板,并传入模板参数 int 和 double
    int c = add<int, double>(a, b);
    return 0;
}

在这个例子中,我们调用了 add 函数模板,并将 ab 分别作为其两个参数传递进去,同时使用尖括号 < > 指定了模板参数类型为 intdouble。函数模板会根据传入的参数类型来推断出返回值的类型。

注意,对于函数模板,编译器不能自动推断出模板参数类型,因此必须显式地指定。

但在某些情况下,编译器也可以自动推断出模板参数类型,例如:

int main()
{
    int a = 1;
    double b = 2.5;
    // 自动推断出模板参数类型为 int 和 double
    int c = add(a, b);
    return 0;
}

在这个例子中,我们没有显式地指定模板参数类型,而是直接调用了 add 函数模板,并将 ab 分别作为其两个参数传递进去,编译器根据参数类型自动推断出模板参数类型为 intdouble