如果返回类型碰巧是模板参数,编译器是否不能推断出函数的返回类型?否则我在以下代码中出错。
#include <iostream>
template <typename TT>
TT retBoolFail(bool a) {
return true;
}
template <typename TT>
void retBoolSuccess(bool a, TT& ret) {
ret = true;
return;
}
int main() {
bool ret;
retBoolSuccess(true, ret); // Success
retBoolFail(true); // Failure
return 0;
}
第'RetBoolFail(true)行失败,并出现以下错误。
-*- mode: compilation; default-directory: "~/work/c++/tupleTemplate/" -*-
Compilation started at Thu Mar 21 16:52:50
g++ -c simpletemp.cc -std=c++1z -g; g++ -o simpletemp simpletemp.o
simpletemp.cc: In function ‘int main()’:
simpletemp.cc:17:21: error: no matching function for call to ‘retBoolFail(bool)’
retBoolFail(true); // Failure
^
simpletemp.cc:4:4: note: candidate: template<class TT> TT retBoolFail(bool)
TT retBoolFail(bool a) {
^
simpletemp.cc:4:4: note: template argument deduction/substitution failed:
simpletemp.cc:17:21: note: couldn't deduce template parameter ‘TT’
retBoolFail(true); // Failure
^
Compilation finished at Thu Mar 21 16:52:50
谢谢。
答案 0 :(得分:3)
否,仅在参数列表中进行推导。您可以改用auto
,也可以仅使其成为具有硬编码返回类型的非模板函数。
答案 1 :(得分:1)
类型推导不适用于仅用于函数模板参数的返回类型。
您必须使用
retBoolFail<bool>(true);
您必须提示编译器推断返回类型的类型。即使在函数模板中使用auto
仍然需要您在调用站点提示编译器。
答案 2 :(得分:1)
将模板名称用作要调用的函数时,模板参数推导仅使用函数参数和模板函数签名,而不使用函数主体。
在标准中很难更改此规则的一个原因是,如果名称重载,事情将如何进行。完整的图片如下:
名称查找可找到一组函数和函数模板。
对于集合中的每个功能模板,模板参数均由显式模板参数,推导和/或默认模板参数确定。如果推导失败,或者如果将确定的模板参数替换为函数类型导致无效,则该函数模板将从重载集中丢弃为不可行。
对于每个函数签名(无论是否来自模板),都将进行检查以查看函数参数和函数参数是否匹配。如果不是,则该功能不可行,并从重载集中丢弃。
过载分辨率比较其余可行的功能。对于大多数过程,模板中的函数类型与非模板函数一样,但是有一些针对函数模板专业化的最终决胜规则。
如果重载解析选择了功能模板特化,并且上下文是需要存在功能定义的上下文,则功能实例也将实例化以生成该定义。如果将模板参数参数替换为函数主体会导致某些无效操作,则程序格式错误。
因此,在实例化函数模板的函数类型和是否实例化时,以及实例化函数主体时,以及在两种情况下无效模板参数使用的结果之间,存在区别。从功能体中推论会混淆这一点。
但是在某些其他情况下,函数模板返回类型中的模板参数可以参与模板参数推导。 (此列表可能并不完整。)
如果从函数模板名称(或其指针大小写的地址)初始化了指向函数的指针或对函数的引用,则模板参数推导涉及返回类型:
template <typename TT>
TT f();
unsigned int (&func_ptr)() = f; // TT deduced as unsigned int
int g(double (*)());
int g_of_f = g(f); // TT deduced as double
一个类或类模板可以具有转换功能模板。然后,具有该类类型的表达式的某些用法可以隐式使用该模板,这需要在其返回类型中推导模板参数(这也是其声明中operator
关键字之后的内容)。
class A {
public:
template <typename TT>
operator std::shared_ptr<TT>() const;
};
std::shared_ptr<int> p = A{}; // TT deduced as int
还要注意,使用“占位符类型”作为其返回类型的函数或函数模板(该返回类型包含关键字auto
)的确从主体的return
语句(即不会因为“ if constexpr
”而被跳过)。尽管没有模板头的函数仍然只是具有一种特定类型的一个函数,而不是函数模板,并且这种推论是与任何模板参数推论分开的步骤。
auto retBool(bool a) {
return true; // return type is bool
}
template <typename T>
constexpr const auto* constify(T* ptr) {
return ptr; // return type is const T* (T* if T is already const)
}