Syd*_*ius 4 c++ syntax templates
模板语句的"类"部分有什么作用?
例:
template <class T>
class Something
{
public:
Something(const T &something);
}
Run Code Online (Sandbox Code Playgroud)
还有什么可以去那里?我通常只看"班级".
该class
关键字意味着同样的事情typename
大部分关键字.它们都表明T是一种类型.
关键字之间唯一的区别class
和typename
是class
可以用来提供类模板模板参数模板,而typename
不能.考虑:
template<template <class T> class U> // must be "class"
std::string to_string(const U<char>& u)
{
return std::string(u.begin(),u.end());
}
Run Code Online (Sandbox Code Playgroud)
唯一可以代替class
或typename
关键字的东西是整数类型.例如:
template<std::size_t max>
class Foo{...};
...
Foo<10> f;
Run Code Online (Sandbox Code Playgroud)
有关具体示例,请std::bitset<N>
参阅标准库.
要定义模板参数,您需要告诉编译器参数是类型还是值.
如果我没记错的话,C++委员会不愿意在C++语言中添加新的关键字,因此,他们决定授权以下符号:
template<int I>
int getTwice()
{
return I * 2 ;
}
template<class T>
std::string getType(const T & t)
{
return typeid(t).name() ;
}
void doSomething()
{
std::cout << "25 : " << getTwice<25>() << std::endl ;
std::cout << "5 : " << getTwice<5>() << std::endl ;
std::cout << "type(25) : " << getType(25) << std::endl ;
std::cout << "type(25.5) : " << getType(25.5) << std::endl ;
std::cout << "type(abc) : " << getType("abc") << std::endl ;
}
Run Code Online (Sandbox Code Playgroud)
以g ++为单位的输出:
25 : 50
5 : 10
type(25) : i
type(25.5) : d
type(abc) : A4_c
Run Code Online (Sandbox Code Playgroud)
第一种表示法是一个值的模板.所以,我们在模板声明中有值的类型:
// "I" is the value, and "int" is the type of the value
template <int I>
Run Code Online (Sandbox Code Playgroud)
第二种表示法是未知类型的模板,并且类型未"已知"的事实由"class"关键字标记.因此,在这种情况下,"类"意味着"类型".
// "T" is a type... And "class" is the "this-is-a-type" keyword
template <class T>
Run Code Online (Sandbox Code Playgroud)
你会注意到,使用第二种表示法,尽管有class关键字,但T可以是...一个int或另一种内置类型.但是,比起添加新关键词更好的是有这种好奇心,你不同意吗?...
一切都很好,直到有人写下面的代码:
template<class T> // T could be any STL container, for example a vector<char>
void printContainerData(const T & t)
{
std::cout << "aVector:" ;
for(T::const_iterator it = t.begin(), itEnd = t.end(); it != itEnd; ++it)
{
std::cout << " " << (*it) ;
}
std::cout << std::endl ;
}
Run Code Online (Sandbox Code Playgroud)
其中T :: const_iterator是一个类型,当然......但是,它可能是类型为T的类的静态成员,因此是一个值.编译器可能很混乱.
解决方案是告诉编译器T :: const_iterator 实际上是一个类型......这将导致这种表示法:
for(class T::const_iterator it = t.begin(), // etc.
Run Code Online (Sandbox Code Playgroud)
但是这被认为不可能/正确(类是关于类声明,不是?).于是,拖着他们的脚,他们决定一个关键字是确实需要告诉编译器的符号是一个类型,而不是一个值.
我想,"类型"没有被考虑,因为将其作为关键字会破坏很多代码.所以改为使用typename.使用typename,我们可以写:
for(typename T::const_iterator it = t.begin(), // etc.
Run Code Online (Sandbox Code Playgroud)
为了保持一致性,我们应该使用:
template <typename T>
Run Code Online (Sandbox Code Playgroud)
当T应该是一个类型,而不是一个值.但出于兼容性原因,旧的表示法:
template <class T>
Run Code Online (Sandbox Code Playgroud)
仍然是授权的.
eben提出了上面的答案,我想回答一个答案,因为它非常有趣:
template<template <class T> class U> // must be "class"
std::string to_string(const U<char>& u)
{
return std::string(u.begin(),u.end());
}
Run Code Online (Sandbox Code Playgroud)
我只会评论它的"含义"(这个代码不能与我的g ++编译器上的STL容器一起使用,但这不是重点,我猜):有一刻,它对U的约束说:"U是一个在类型T上模板化的类.这是部分:
template <class T> class U
Run Code Online (Sandbox Code Playgroud)
哪个也可以写:
template <typename T> class U
Run Code Online (Sandbox Code Playgroud)
因为U实际上只是一个类(而不是内置类型),而T是一个类型,任何类型.
下一行,它说U专门针对char:
std::string to_string(const U<char>& u)
Run Code Online (Sandbox Code Playgroud)
所以,这个"通用代码"只适用于U,如果U被声明为:
template<typename T>
class U
{
// Etc.
} ;
Run Code Online (Sandbox Code Playgroud)
并且U在char上实例化:
U<char> u ;
// etc.
to_string(u)
Run Code Online (Sandbox Code Playgroud)
但有一件事被遗忘了:Eben提出的符号可以用两种方式写成:
template<template <class T> class U>
std::string to_string(const U<char>& u)
template<template <typename T> class U>
std::string to_string(const U<char>& u)
Run Code Online (Sandbox Code Playgroud)
第二个"class"关键字本身不是"type"关键字.它是一种类型,它是T上的模板类.因此令人困惑的符号.
编写Eben代码的另一种方法是删除上面的约束,如下所示:
template<typename U>
std::string to_string(const U & u)
{
return std::string(u.begin(),u.end());
}
Run Code Online (Sandbox Code Playgroud)
让编译器发挥其魔力:
std::list<char> myList ;
// etc.
std::cout << to_string(myList) << std:endl ;
Run Code Online (Sandbox Code Playgroud)
(Eben的代码不适用于我的g ++编译器上的"char"模板化的STL容器,例如...)