模板可以在不丢失信息的情况下传递参数类型
A template can pass argument types without loss of information
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);
时,您坚持要求编译器调用sum
的short
版本:即short sum (short a, short b)
在此过程中,l
s被转换为short
类型这正是编译器警告您的:如果l
对short
来说太大,那么您离未定义的行为只有一毛不拔的距离。这个过程与模板函数本身无关,因此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=短整型
因此类型被保留
- 为什么在这种情况下,bool 类型的输出等于 0?
- C++默认情况下,指针类型数组的元素是否保证初始化为 nullptr?
- 如何在没有实例的情况下获取非静态方法的类型?
- 如何在不破坏现有应用程序的情况下更改 API 中 stl 容器的数据类型?
- 是否可以在不使用 decltype 的情况下推断先前定义的 extern 变量的类型
- 在没有标识符的情况下如何读取复杂的C++类型声明?
- MSVC 在不知道类型的情况下评估上下文(和错误)
- 我们可以在不知道其真实类型的情况下将基类指针转换为派生类指针吗?
- 如何在不给它任何类型(如整数)的情况下定义某物?
- 为什么我不能在不进行任何转换的情况下将浮点数放入任何类型的 ptr 中?
- 将类型映射到整数值后,如何在给定整数值的情况下恢复类型?
- 如何在不违反类型别名规则的情况下解释消息负载?
- msgpack:在不知道类型的情况下解包自定义类
- 对于多态类型T,如何在没有类型T实例的情况下获得指向T的虚拟表的指针
- 在这种特殊情况下,我是否需要在共享内存中使用原子类型
- 为什么在以下情况下不需要为依赖类型使用typename
- 有没有办法在没有reinterpret_cast的情况下保存多种类型的指针?
- 如何定义可以在没有联合的情况下容纳uintptr_t或uint32_t的类型?
- 推荐的方法在不初始化值的情况下使数组类型为 std::unique_ptr?
- 为什么默认情况下C++类型不是常量?