对隐式和显式模板声明感到困惑

时间:2010-06-03 22:28:24

标签: c++ templates

我对隐式声明和显式声明感到困惑。我不知道为什么你需要明确说出或在某些时候。例如,

在我的main.cpp

#include <iostream>
#include "Point.h"

int main()
{
    Point<int> i(5, 4);
    Point<double> *j = new Point<double> (5.2, 3.3);
    std::cout << i << *j;
    Point<int> k;
    std::cin >> k;
    std::cout << k;
}

代表Point<int> k。为什么我必须使用显式声明?否则我会收到编译错误。或者我的Point.h文件中编码不正确?

Point.h:

#ifndef POINT_H
#define POINT_H

#include <iostream>

template <class T>
class Point
{
public:
    Point();
    Point(T xCoordinate, T yCoordinate);

    template <class G>
    friend std::ostream &operator<<(std::ostream &out, const Point<G> &aPoint);

    template <class G>
    friend std::istream &operator>>(std::istream &in, const Point<G> &aPoint);

private:
    T xCoordinate;
    T yCoordinate;
};

template <class T>
Point<T>::Point() : xCoordinate(0), yCoordinate(0)
{}

template <class T>
Point<T>::Point(T xCoordinate, T yCoordinate) : xCoordinate(xCoordinate), yCoordinate(yCoordinate)
{}


template <class G>
std::ostream &operator<<(std::ostream &out, const Point<G> &aPoint)
{
    std::cout << "(" << aPoint.xCoordinate << ", " << aPoint.yCoordinate << ")";
    return out;
}

template <class G>
std::istream &operator>>(std::istream &in, const Point<G> &aPoint)
{
    int x, y;
    std::cout << "Enter x coordinate: ";
    in >> x;
    std::cout << "Enter y coordinate: ";
    in >> y;
    Point<G>(x, y);

    return in;
}

#endif

3 个答案:

答案 0 :(得分:8)

对于类模板,必须明确指定模板参数。

对于函数模板,可以隐式推断模板参数。

Point是一个类,因此需要明确声明。

答案 1 :(得分:2)

您的operator>>不正确。您需要修改aPoint

的值
template <class G>
std::istream &operator>>(std::istream &in, const Point<G> &aPoint)
{
    std::cout << "Enter x coordinate: ";
    in >> aPoint.x;
    std::cout << "Enter y coordinate: ";
    in >> aPoint.y;

    return in;
}

此外,除了读取数据之外,operator>>做任何事情绝对不是标准。所以下一次迭代将是:

template <class G>
std::istream &operator>>(std::istream &in, const Point<G> &aPoint)
{
    in >> aPoint.x;
    in >> aPoint.y;

    return in;
}

这也不理想,因为输出格式与输入格式不同。

答案 2 :(得分:1)

我几乎只是在KennyTM的答案中编辑了一些额外的细节,但是到底是什么:

对于类模板,必须始终明确指定模板参数,或者将其作为默认模板参数提供。

对于函数模板,通常可以自动推断模板参数,但有时您需要(或想要)明确指定它们。对于一个相当常见的示例,请考虑以下模板:

template <class T>
void func(T const &a, T const &b) { }

如果使用两种不同类型的参数(比如int和double)调用它,并且每种类型都可以隐式转换为另一种类型,则编译器通常无法决定使用哪种类型。您可以通过使用强制转换将两个参数显式转换为相同类型,或通过显式指定模板参数来解决此问题:

func(1, 1.0);          // ambiguous, T could be int or double
func((double)1, 1.0);  // unambiguous
func<double>(1, 1.0);  // also unambiguous