定义函数模板
Defining function templates
我想知道下面示例中的表达式cT::value_type
告诉编译器什么?我可以用value_type
这个词写任何我不会写的东西——它无论如何都会构建。代码似乎试图告诉编译器"cT
类型应该具有某个属性(o可能是向量成员,但在模板定义中不可见),该类型将用于第二个函数参数"。我的理解离现实有多远?
编译器如何知道两个参数都应该作为字符串:
joinContainer(s1, ':');
在编译器的地方,我希望有类似的东西
joinContainer<string,string>(s1, ':');
或者事件可能是
<string>joinContainer<string,string>(s1, ':');
完整代码:
// join.cpp by Bill Weinman <http://bw.org/>
#include <iostream>
#include <vector>
using namespace std;
template<typename cT, typename retT = cT, typename sepT = decltype(cT::value_type)>
retT joinContainer(const cT & o, const sepT & sep) {
retT out;
auto it = o.begin();
while(it != o.end())
{
out += *it;
if(++it != o.end()) out += sep;
}
return out;
}
int main( int argc, char ** argv ) {
string s1("This is a string");
string s2("This is also a string");
string s3("Yet another string");
// join the characters of a string
cout << joinContainer<string, string>(s1, ':') << endl;
// join strings from a vector, returning a string
vector<string> vs({s1, s2, s3});
cout << joinContainer<vector<string>, string>(vs, ", ");
return 0;
}
这个例子看起来有点不合逻辑。基本上是这样的:
template<typename T = Foo>
void f(const T & x)
{
// print x, whatever...
}
("typename T = Foo
"与"typename sepT = decltype(cT::value_type)
"类似,"const T & x
"与"const sepT & sep
"类似)。
现在,有多少种方法可以调用这个函数?只有一个:
f(obj); // whatever type obj is
也就是说,您必须始终传递一个参数,并且T
将始终被推导出来,因此Foo
永远不会被使用。
(好吧,你也可以强制使用模板参数,比如f<Bar>(obj);
,但Foo
仍然不会被使用,无论如何你都不应该这样做。)
一个更合乎逻辑的例子是:
template<typename T = Foo>
void g(const T & x = T())
{
// print x, whatever...
}
现在,由于模板参数的默认值(类型)和函数参数的默认数值,您可以使用或不使用参数来调用它:
g(obj);
g(); // equivalent to g(Foo());
在无参数调用中,使用T
的默认Foo
。
此外,"decltype(cT::value_type)
"是无效:decltype
采用表达式,而不是类型。也许作者的意思是typename sepT = typename cT::value_type
(需要额外的"typename
")。
编译器从2中获取sepT模板参数。函数参数,因此它可能永远不会使用默认参数(cT::value_type
)。因此,它可能永远不会实例化使用第三个模板参数的默认值的模板。
至于你的第二个问题,为什么你可以写joinContainer(s1, ':');
,而且它有效。编译器拥有所需的所有信息。1。和3。模板参数是从函数参数中推导出来的。2。没有指定template参数,但在定义中有一个默认参数,所以编译器使用它。
joinContainer(s1, ':');
cT - type std::string (deduced from s1)
retT - type std::string (default value used, which is the same as cT)
sepT - type const char (deduced from ':')
joinContainer<string,string>(s1, ':');
cT - type std::string (because you specified in the template parameters)
retT - type std::string (because you specified in the template parameters)
sepT - type const char (deduced from ':')
note: if s1 would not be of type std::string there would be a compiler error
<string>joinContainer<string,string>(s1, ':');
Will not compile.
- 仅在函数模板中为那些定义了函数的类型执行函数
- 在 C++20 中是否不再允许在 std 中对程序定义类型的函数模板进行专用化?
- 模板推导:为什么函数指针模板定义在常量和/或引用时不匹配?
- 使用定义函数模板别名
- 2个模板化类的非模板友元函数未定义引用错误
- 何时需要实例化函数模板定义?
- 使用表达式 SFINAE 的函数模板的类外定义
- 将类成员函数的模板定义放在 CPP 文件中C++隐式实例化而不是 .H 允许吗?
- 如何为自定义模板对象创建专门的函数模板
- 在模板定义中调用非静态constexpr成员函数
- 我应该声明我的函数模板专业化还是定义它们就足够了
- 即使我正在.cpp文件中实例化一个伪对象,.cpp文件内模板函数的定义也不起作用
- 使用模板模板参数进行模板定义的函数专用化
- 使用用户定义的转换运算符推导函数模板参数
- 如何定义函数模板中使用的函数?
- 为什么用户定义的转换函数模板不能有推导的返回类型?
- 关于函数模板中定义的 lambda 闭包类型可以说些什么?
- 错误:重新定义函数模板(或 C2995)
- 如何严格定义函数模板显式实例化规则
- 将函数模板定义为类模板的回调