模板可以在不丢失信息的情况下传递参数类型

A template can pass argument types without loss of information

本文关键字:情况下 类型 参数 信息      更新时间:2023-10-16

Straustrup在他的书《C++编程语言》中谈到了在不丢失信息的情况下传递模板参数,"模板可以传递参数类型而不丢失信息;"

他所说的信息丢失是什么意思?

template <typename T>
T sum (T a, T b)
{
    return a + b;
}
int main ()
{
  long l = 212;
  sum<short> (l, l);
}

Visual C++11编译器返回警告

warning C4244: 'argument' : conversion from 'long' to 'short', possible loss of data

这就是他所指的吗?

在编写sum<short> (l, l);时,您坚持要求编译器调用sumshort版本:即short sum (short a, short b)

在此过程中,l s被转换为short类型这正是编译器警告您的:如果lshort来说太大,那么您离未定义的行为只有一毛不拔的距离。这个过程与模板函数本身无关,因此Stroustrup的断言仍然成立:在编译时没有类型信息的丢失。

没有。

如果您想制作一个不使用模板的通用sum函数,则需要选择一种特定的类型来实现。这迫使类型转换,因此可能会丢失信息。

该模板允许您为任何类型编写sum(l,l),并且不会丢失任何内容。你可以写sum(string1, string2),没问题。换句话说。在和定义中,您知道操作数的原始类型。

通过显式选择类型,您有意禁用此机制,通过强制编译器使用您选择的实例化。这与使用显式类型编写sum没有什么不同。在你的情况下,你不小心强行缩小了类型。但实际使用的类型并不重要。

他的话不是关于整数转换的。至少我认为是这样。模板比避免类型缩小更重要,目的也更大。

他的观点可以通过对程序进行一个小的修改来更好地说明:

#include <iostream>
#include <typeinfo>
template <typename T>
T sum (T a, T b)
{
    std::cout << "summing two values of type: " << typeid(T).name() << std::endl;
    return a + b;
}
int main ()
{
    long l = 212;
    sum(l, l);
    short s = 212;
    sum(s, s);
}

示例输出:(如果您在Visual Studio上,可能会有所不同)

summing two values of type: l
summing two values of type: s

请注意,完整的类型信息在模板函数的每个实例化中都是可用的。这允许编译器在编译时执行完整的类型检查,从而减少了在运行时需要捕获的编程错误的机会。

他指的不是值,而是参数的类型。在您的示例中,类型T将是短int,它不会被更改。这允许编译器执行各种优化,比如内联,还可以提高类型安全性。

您可以使用TD模板使用以下技巧验证类型是否被保留:

template<typename T> class TD;
template <typename T>
T sum (T a, T b)
{
    TD<T> aaa;
    return a + b;
}
int main ()
{
  long l = 212;
  sum<short> (l, l);
}

编译器将发出一个错误,向您提供实际类型T的信息,对于gcc,它将是:

main.cpp: In instantiation of 'T sum(T, T) [with T = short int]':
main.cpp:14:19:   required from here
main.cpp:6:11: error: 'TD<short int> aaa' has incomplete type
     TD<T> aaa;

T=短整型

因此类型被保留

相关文章: