bob*_*obo 13 c++ syntax templates
我习惯用尖括号来指定一个类型,作为参数:
vector<int> vecOfInts ;
Run Code Online (Sandbox Code Playgroud)
但是在rapidjson中,有这样的代码:
document.Parse<0>(json) ;
Run Code Online (Sandbox Code Playgroud)
该document.Parse方法的签名是:
template <unsigned parseFlags>
GenericDocument& Parse(const Ch* str) {
RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
GenericStringStream<Encoding> s(str);
return ParseStream<parseFlags>(s);
}
Run Code Online (Sandbox Code Playgroud)
我不知道你可以在尖括号内传递一个值 - 思想尖括号仅用于类型名称.
这里的代码是什么,为什么他在尖括号中传递一个值?
这是一个好主意吗?什么时候?
tem*_*def 20
这里有两个不同的因素.
首先,可以定义参数化的模板,而不仅仅是类型.例如,这是一个简单的数组类型:
template <typename T, size_t N> struct Array {
T arr[N];
};
Run Code Online (Sandbox Code Playgroud)
我们可以使用这个
Array<int, 137> myArray;
Run Code Online (Sandbox Code Playgroud)
我们知道vector<int>并且vector<double>是不同的类型.但是现在我们还必须指出的是,Array<int,137>和Array<int,136>是不同的类型.
其次,在使用模板时,编译器必须能够为所有模板参数找出值.当您使用模板类时,这就是您通常指定所有模板参数的原因.vector x例如,你没有说,而是说出类似的话vector<double> x.使用模板函数时,编译器大多数时候都可以找出参数.例如,要使用std::sort,你只需说出类似的话
std::sort(v.begin(), v.end());
Run Code Online (Sandbox Code Playgroud)
但是,你也可以写
std::sort<vector<int>::iterator>(v.begin(), v.end());
Run Code Online (Sandbox Code Playgroud)
更明确.但有时候,你有一个模板函数,并不是所有的参数都可以计算出来.在您的示例中,我们有:
template <unsigned parseFlags>
GenericDocument& Parse(const Ch* str) {
RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
GenericStringStream<Encoding> s(str);
return ParseStream<parseFlags>(s);
}
Run Code Online (Sandbox Code Playgroud)
请注意,parseFlags模板参数不能仅从函数的参数中推导出来.因此,要调用该函数,必须指定模板参数,否则编译器无法解决该问题.这就是你写这样的东西的原因
Parse<0>(myString);
Run Code Online (Sandbox Code Playgroud)
这里,0是模板参数(在编译时解析),并且myString是实际参数(在运行时解析).
实际上,您可以使用组合了一些类型推断和一些显式类型参数的方法.例如,在Boost中,有一个函数lexical_cast可以与字符串类型进行转换.要从非字符串类型转换为字符串类型的函数签名是
template <typename Target, typename Source>
Target lexical_cast(const Source& arg);
Run Code Online (Sandbox Code Playgroud)
在这里,如果你调用lexical_cast,编译器可以弄清楚它是什么Source,但如果Target没有一些提示它就无法推断出来.lexical_cast因此,要使用,你会写一些类似的东西
std::string myString = boost::lexical_cast<std::string>(toConvertToString);
Run Code Online (Sandbox Code Playgroud)
更一般地说,编译器说你必须指定一些模板参数(可选0),它会尝试推断其余的.如果可以,太棒了!如果不是,那就是编译时错误.使用它,如果你愿意,你可以写一个像这样的函数
template <int IntArgument, typename TypeArgment>
void DoSomething(const TypeArgument& t) {
/* ... */
}
Run Code Online (Sandbox Code Playgroud)
要调用此函数,您必须像这样调用它:
DoSomething<intArg>(otherArg);
Run Code Online (Sandbox Code Playgroud)
在这里,这是有效的,因为你必须明确告诉编译器是什么IntArgument,但编译器可以TypeArgument从参数的类型推断出来DoSomething.
希望这可以帮助!