首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >模板函数参数默认值的数据类型与实例化数据类型不同

模板函数参数默认值的数据类型与实例化数据类型不同
EN

Stack Overflow用户
提问于 2018-08-28 05:06:24
回答 3查看 214关注 0票数 3
代码语言:javascript
运行
复制
 #include <iostream>
 #include <string>

 template <typename T>
 void f(T x = std::string{""})
 {
   std::cout << '[' << x << ']' << std::endl;
 }

 int main()
 {
   f(23); // Case 1: Doesn't fail
   f<int>(); // Case 2: Compilation error
   f<int>(23); // Case 3: Doesn't fail
 }

不应该情况1和案例3也失败,因为函数模板是由int实例化的,耳聋值的类型是std::string

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-08-28 05:21:44

情况1和案例3不应该也失败吗?因为函数模板是由int实例化的,耳聋值的类型是std::string?

不,不应该。请看下面的原因。如果您希望它失败,那么您应该将template.定义为正则函数,接收std::string类型的参数,而不是函数

您所拥有的是默认参数实例化的情况,参见[temp.inst]中的

如果函数模板f的调用方式要求使用默认参数,则查找相关名称,检查语义约束,并实例化.如果默认参数是函数模板专门化中使用的初始化器,则.这种分析称为默认参数实例化。实例化的默认参数然后用作f. 的参数。

当你写:

代码语言:javascript
运行
复制
template <typename T>
void f(T x = std::string{""}){...}

这意味着""x 的默认参数,只有在调用没有任何参数()的情况下。例如,在您的案例2中。

您的模板函数被定义为对int或其他各种类型都很好地进行了安装。

例如这里(案例1)

代码语言:javascript
运行
复制
f(23);

它被隐式地(通过基于参数类型的推理)实例为f<int>(),因为23在规范中被定义为int文本。类型为x的参数int接收在调用站点中提供的23的非默认值。

在这里(案例2)

代码语言:javascript
运行
复制
f<int>();

正是上面的标准子句发挥作用的地方:成功地实例化了f(),但没有为它提供参数,因此实例化的默认参数随后被用作f的参数。因此编译失败,因为参数x的默认值被定义为std::string,没有将其转换为int类型。它实际上相当于在声明为f("") void f(int x).的函数上调用。

在这里(案例3)

代码语言:javascript
运行
复制
f<int>(23);

再次显式,这次是,您在调用站点.上提供了正确的参数类型。

票数 3
EN

Stack Overflow用户

发布于 2018-08-28 05:15:43

只有在没有为T x = std::string{""}提供arg的情况下才执行x

代码语言:javascript
运行
复制
f(23)

隐式实例化到f<int>。不使用x的默认值,因为23是作为int文本提供的。

代码语言:javascript
运行
复制
f<int>()

现在,Tint类型的,但是您要用一个std::string分配给x

代码语言:javascript
运行
复制
f<int>(23)

T仍然是int,与案例1相同

票数 4
EN

Stack Overflow用户

发布于 2018-08-28 06:49:36

@Abigail提供的答案解释了为什么case 1和3没有失败,另外让我指出函数模板没有多大意义。一个具有默认值的参数的函数应该是可调用的,如:

代码语言:javascript
运行
复制
void g(std::string = "") { /* ... */ }

g(); // Use default parameter
g("non-default");

相反,可以用给定的参数调用函数模板。

代码语言:javascript
运行
复制
f("non-default");

但不是没有任何参数,因为编译器不会从默认参数中推断模板类型。

代码语言:javascript
运行
复制
f(); // Doesn't compile

我建议将模板更改为

代码语言:javascript
运行
复制
 template <typename T = std::string>
 void f(T x = T{})
 {
     // same as before
 }

它修复了f()实例化。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52050458

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档