首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么我们必须做模板<class/typename> T而不是模板T.

在C++中,模板的定义和使用需要使用<class/typename> T的形式,而不是直接使用T。这是因为C++的语言设计者为了解决模板的类型推导问题,以及为了避免与其他语言元素的混淆,决定使用<class/typename> T的形式来明确指出这是一个模板类型参数。

具体来说,<class/typename> T表示T是一个类型参数,而不是一个值参数或者其他类型的参数。这样,编译器就可以根据T的类型来推导出模板的实例化类型,从而实现模板的泛型编程。

例如,在定义一个模板类时,可以使用<class/typename> T来指定类型参数:

代码语言:txt
复制
template<typename T>
class MyClass {
    T data;
    // ...
};

在使用模板时,也需要使用<class/typename> T来指定模板参数的类型:

代码语言:txt
复制
MyClass<int> myObj; // 使用int类型实例化模板类

因此,我们必须使用<class/typename> T来定义和使用模板,以便编译器能够正确地推导出模板的实例化类型,并生成正确的代码。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

C++打怪升级(八)- 泛型编程初见

; 这一组函数代码的可维护性差,要改就需要更改一组函数,也很麻烦; 基于类似这样的原因,C++提出了泛型编程的概念,我们只需要写出一个函数模板不是具体的函数,我们直接使用这个函数模板,具体的函数由编译器自动生成...,优先调用具体函数不是函数模板; 如果我们显式使用函数模板生成的具体函数也可以正常运行得到结果; 这说明我们实现的具体函数和函数模板推导生成的具体函数是不同的函数,函数地址不同; 即我们写的具体函数与函数模板推导生成的具体函数的函数名修饰规则是不同的...只能满足其中一种类型,不是多种; 类模板随之而来,利落的解决了这个问题,达到了我们想创建哪个类型的类都可以的目的。...,中写实例化的类型 ,注意类模板名字不是真正的类,实例化的结果才是真正的类(也就是类模板名加上具体的类型是真正的类名); 这里有个问题,类模板实例化为什么必须在其后加上呢?...或者说为什么我们需要指定类模板实例化的类型不是像函数模板实例化那样由编译器推导类型再实例化呢?

81120

C++箴言:理解typename的两个含义

当然,这听起来有些愚蠢,但它是可能的,编写 C++ 解析器的人必须考虑所有可能的输入,甚至是愚蠢的。   ...直到 C 成为已知之前,没有任何办法知道 C::const_iterator 到底是不是一个 type(类型),当 template(模板)print2nd 被解析的时候,C 还不是已知的。...iter 的 declaration(声明)仅仅在 C::const_iterator 是一个 type(类型)时才有意义,但是我们没有告诉 C++ 它是, C++ 就假定它不是。...假设我们在写一个取得一个 iterator(迭代器)的 function template(函数模板),而且我们要做一个 iterator(迭代器)指向的 object(对象)的局部拷贝 temp,我们可以这样...)),我们必须让它被 typename 前置。

4.7K20
  • C++11 JNI开发中RAII的应用(一)--制作基础工具

    struct时返回resource的地址 //这里->操作符使用了函数模板实现,用到了is_pointer和is_class两个type_trait来判断T的类型, //如果T不是指针,也不是class...(resource); }//T和_T不相等且_Tclass/struct时直接将resource转换为_T的引用 template typename...(resource); }//T和_T不相等且_T是指针时调用static_cast将resource转换为_T....//这里用到了is_same来判断模板参数类型是否相同。其实这里应该写得更严谨一些,不仅要判断_Tclass,还要判断T也是class,而且T和_T是继承关系,暂时这么写了,以后再改。...丢掉JNIEnv*拖油瓶 当函数封装越来越多层的时候,总是带着JNIEnv*还真是麻烦,所以在做这件事儿之前,我们要先把调用JNI函数时必须用到的JNIEnv*这个拖油瓶给处理掉。

    38910

    【C++】—通俗易懂的理解C++中的模板

    1.函数模板 1.1 函数模板的概念   函数模板代表了一个函数的家族,这个函数不受类型的限制,比如可以传int类型也可以传double类型,在使用时被参数化,根据实参的类型产生特定类型的函数。...1.2 函数模板的格式 template 返回值类型 函数名(参数列表) {} template void Swap(T& left, T& right...1.3 函数模板的原理 函数模板不是一个函数,而是编译器按使用方式而生成特定类型函数的一个摸具。...1.2 类模板的格式 template class模板名 {  类中成员定义 }; //类模板 template class Point {...* x + y * y); } }; Print类模板中有两个变量x和y,它们都是类型T.构造函数接受两个参数来初始化x和y,distanceFromOrigin计算并返回点到原点的距离。

    5410

    【C++篇】引领C++模板初体验:泛型编程的力量与妙用

    注意:typename是用来定义模板参数关键字,也可以使用class(切记:不能使用struct代替 class),下文会讲到 1.2.3 示例:通用的交换函数 那我们就可以使用模板来编写交换函数,它可以交换任意类型的数据...typenameclass 在定义模板时,typenameclass是可以互换的。...在C++中,类模板的实现与普通类有一个显著的区别:模板是在编译时根据实际类型实例化的,不是像普通的类那样在编译期和链接期处理。...模板无法这样,因为它需要知道使用时的类型才能生成实际的代码。 2.4.4 解决方案:将声明和定义放在同一个头文件中 为了避免上述问题,C++的惯用方法是将类模板的声明和定义都放在同一个头文件中。...模板的匹配规则如下: 优先调用非模板函数:如果存在一个与实参完全匹配的非模板函数,编译器将优先调用非模板函数,不是通过模板生成一个实例。

    18310

    C++:18---函数模板(template)

    模板参数列表不能为空 模板参数既可以用typename声明,也可以使用class声明。...不过建议前者 //定义模板以及一个函数模板 template int compare(const T &v1, const U &v2); int main...但是这些关键字必须放在函数的返回值类型前面,模板参数列表的后面 template //正确inline T func(T const&);constexpr template //错误,constexpr位置错误T func2(T const&); 六、定义类型无关的代码 当我们定义函数模板时,如果函数能处理的功能只限于一些特定的情况,不能作用于大多数的情况...v2)return 1;return 0;} 下面我们编写了这个函数模板,也可以用于传入指针也可以正常使用的函数模板(但是还不是最完美的,所以在定义时,要考虑各种因素达到更高的标准) template

    1.1K50

    C++模板编程:深入理解分离编译的挑战与解决方案

    ::iterator) // 我们需要使用typename来告诉编译器T::some_nested_type是一个类型 // 但在这个例子中,我们不需要这样...然而,在注释中,我提到了如果T有一个嵌套类型,并且我们想要在模板内部引用它作为另一个类型的一部分,那么我们就需要使用typename来明确指定这是一个类型名称。...template class MyClass { public: void doSomething() {...与类模板特化类似,函数模板特化也分为全特化和偏特化(尽管函数模板的全特化在语法上是通过函数重载来实现的,不是真正的模板特化语法)。...<< std::endl; } // 显式实例化 template class MyTemplate; // 这通常不会在源文件中,而是由编译器根据需要自动完成 然而,上面的代码并不是解决模板分离编译问题的正确方法

    12210

    【C++视角】C++之模板(初阶)

    前言: 在学习C语言是经常会遇到一类问题--写各种被频繁调用的函数,这类函数不能被修改类型导致需要反复写,十分繁琐。在C++中,祖师爷为我们创建了一种模板,能够填充各种类型自动生成各种类型的代码。...函数模板格式: template 2.  函数声明或定义 注意事项: ● 自动类型推导,必须推导出一致的数据类型 T,才可以使用。 ● 模板必须要确定出T的数据类型,才可以使用 T 。...函数模板的原理 函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。...所以其实模 板就是将本来应该我们的重复的事情交给了编译器 函数模板的实例化 使用不同类型的参数使用函数模板时,被称为函数的实例化。实例化又分为:隐式实例化和显式实例化。

    8310

    C++ 实现 STL 标准库和算法(二)template 编程和迭代器粗解 实验楼笔记

    如果我们使用add(1,2.0)是会报错的,编译器无法找到add(int,double)。大家可以自己分析一下为什么。...注意,在这里我们一定要显式给出类型 T 。类模板不像是函数模板 ,函数模板会根据参数推断类型。 当然类模板也支持默认参数,但是类模板必须严格从右往左默认化。...成员模板 模板的使用范围是广泛的,不仅可以用作函数模板,类模板,还可以用作 class ,struct ,template class 的成员。而要实现 STL 这是我们必须掌握和使用的特性。...模板如此强大,甚至允许我们模板类中再建立模板类: template class Myclass { public: T a; template <typename type_1 ,...但是如果二者没有差别,为什么还要加入typename呢?

    60710

    C++ 模板沉思录(上)

    我们声明了三个模板参数: typename T:一个普通的类型参数 int N:一个整型参数 template > class Container...由于sizeof的不求值特性,此函数也就不需要(我们也无法提供)函数体了。那么,为什么不直接使用形如“T()”这样的写法,需要声明一个“稻草人函数”呢?...我想,不用我说你就已经明白原因了:这是因为并不是所有的T都具有默认构造函数,如果T没有默认构造函数,那么“T()”就是错误的。...”进行调用(不是认为这个“根本无法被生成出来”的模板是一个错误)。...但显然,任何的两种“数”之间都应该是可以加法的,所以不难想到,我们应该使用两个不是一个模板参数,分别作为lhs与rhs的类型,但是,我们立即就遇到了新的问题。

    1.3K20

    模板进阶:特化与编译链接全解析

    非类型模板 模板参数分为:类型形参和非类型形参 类型形参 类型形参,即在模板初阶中所用的例如class A或typename A此类参数类型,跟在classtypename后。...例如,一个通用的比较函数模板可以比较大多数类型的数据,但在遇到指针时,仅比较指针的地址不是指向的内容,这就可能导致错误的结果。模板特化允许为特定类型提供定制的实现,以解决这些特殊情况下的需求。...示例 假设我们有一个通用的数据存储类模板Data,它可以存储两个不同类型的对象: template class Data { public:...然而,如果我们需要对第一类型是int的情况进行特化,可以使用部分特化: template class Pair { public: Pair(int...这样,当Pair的对象创建时,将调用这个特化版本,不是通用版本。

    15610

    第 16 章 模板与泛型编程

    类型参数前必须使用关键字 classtypename,并且使用 typename指定模板类型参数更为直观。...// 错误,U之前必须加上 classtypename template T calc(const T&, const U&); 除了定义类型参数,还可以在模板中定义非类型参数...template class Blob; // 声明但不定义 默认情况下,C++语言假定通过作用域运算符访问的名字不是类型,而是一个 static数据成员。...在某些情况下,通用模板的定义可能编译失败、的不正确,或者利用特定知识来编写更高效的代码,不是从通用模板实例化。...这时可以定义类或函数模板的一个特例化版本。 当我们特例化一个函数模板时,必须为元模板中的每个模板参数都提供实参。

    1.4K60

    《C++Primer》第十六章 模板与泛型编程

    3.4 模板默认实参与类模板 如果一个类模板为其所有模板参数都提供了默认实参,且我们希望使用这些默认实参,就必须模板名后面加上一个空尖括号对: template class...我们重写一个函数以返回元素值的拷贝不是引用: template auto fcn2(It beg, It end) -> typename remove_reference...定义函数模板特例化 为了处理字符指针(不是数组),可以为第一个版本的compare定义一个模板特例化版本。...一个类模板的部分特例化本身是一个模板,使用它时用户还必须为那些在特例化版本中未指出的模板参数提供实参: // 原始的通用的版本 typename struct remove_reference...特例化成员不是类 假定Foo是一个模板类,包含一个成员Bar,我们可以只特例化该成员: template struct Foo { Foo(const T &t =

    1.9K10

    第 16 章 模板与泛型编程

    类型参数前必须使用关键字 classtypename,并且使用 typename指定模板类型参数更为直观。...// 错误,U之前必须加上 classtypename template T calc(const T&, const U&); 除了定义类型参数,还可以在模板中定义非类型参数...template class Blob; // 声明但不定义 默认情况下,C++语言假定通过作用域运算符访问的名字不是类型,而是一个 static数据成员。...在某些情况下,通用模板的定义可能编译失败、的不正确,或者利用特定知识来编写更高效的代码,不是从通用模板实例化。...这时可以定义类或函数模板的一个特例化版本。 当我们特例化一个函数模板时,必须为元模板中的每个模板参数都提供实参。

    1.5K20

    Modern c++快速浅析

    对于非模板类型参数而言,使用auto进行自动推断会方便很多 template auto是可选项不是必选项 •对于部分情景而言,使用auto能够避免不少低级错误,如Effective...对于刚学习C++不久的人来说,最常见的typename的使用场所就是模板了 template template 上例中typenameclass并无任何差别...初学者选择typename可能会对模板有更好的了解(毕竟若模板传进来的是int,它是内置类型,看起来不是一个class) 进入正题,使用typename可以明确的告诉编译器,后面跟着的这个名字是类中的类型成员...,不是数据成员(例如静态成员变量) class Foo { public: typedef int FooType; int f = 10; }; class Bar { public...::ElemT num; } 知乎-C++ 为什么有时候必须额外写 template?

    19510

    【笔记】《C++Primer》—— 第16章:模板与泛型编程

    ,非类型参数表示的是一个值不是类型,因此非类型参数在编译时会被用户提供或编译器推断的一个常量代替,从而允许我们初始化数组之类 非类型参数可以是整型或指向对象或函数的指针或左值引用,但是注意绑定到非类型整型必须是常量表达式...template class friendTemp2; // 类模板 template class classTemp { // 一对多的友元...,模板实参需要写明白 friend class friendTemp2; }; C11中我们可以让模板类型参数自己成为友元,从而提高了灵活性 由于模板不是一个类型(实例化后才是...,不是重载,因此特例化不会影响函数的匹配。...常用的用法是打开std空间特例化标准库函数 我们甚至可以只特例化类中的某个成员函数不是整个模板,写法其实就是将模板类中的某个函数在外部定义,然后这个定义以特例化模板函数的方法写出即可

    1.5K30
    领券