std::reference_wrapper
没有operator<
,所以唯一的方法ref_wrapper<ref_wrapper
是通过ref_wrapper
成员:
operator T& () const noexcept;
如您所知,std::string
是:
typedef basic_string<char> string;
相关声明为string<string
:
template<class charT, class traits, class Allocator>
bool operator< (const basic_string<charT,traits,Allocator>& lhs,
const basic_string<charT,traits,Allocator>& rhs) noexcept;
对于string<string
这个函数声明模板是通过匹配string
=实例化的,basic_string<charT,traits,Allocator>
它解析为charT
=char
等。
因为std::reference_wrapper
(或其任何(零)基类)不能匹配basic_string<charT,traits,Allocator>
,所以函数声明模板不能实例化为函数声明,也不能参与重载。
这里重要的是没有非模板operator< (string, string)
原型。
显示问题的最少代码
template <typename T>
class Parametrized {};
template <typename T>
void f (Parametrized<T>);
Parametrized<int> p_i;
class Convertible {
public:
operator Parametrized<int> ();
};
Convertible c;
int main() {
f (p_i); // deduce template parameter (T = int)
f (c); // error: cannot instantiate template
}
给出:
In function 'int main()':
Line 18: error: no matching function for call to 'f(Convertible&)'
标准引用
14.8.2.1 从函数调用中推导出模板参数 [temp.deduct.call]
模板参数推导是通过将每个函数模板参数类型(调用它P
)与调用的相应参数类型(调用它)进行比较来完成的,A
如下所述。
(...)
一般来说,推导过程试图找到模板参数值,使推导的值A
与A
(在A
如上所述转换类型之后)相同。但是,有三种情况允许不同:
- 如果原始
P
是引用类型,则推导的A
(即引用所引用的类型)可以比转换后的 cv 更合格A
。
请注意,这是std::string()<std::string()
.
- 转换的
A
可以是另一个指针或指向成员类型的指针,可以A
通过限定转换 (4.4) 转换为推导。
请参阅下面的评论。
- 如果
P
是一个类并且P
具有simple-template-id的形式,那么转换后的A
可以是 deduced 的派生类A
。
评论
这意味着在本段中:
14.8.1 显式模板参数规范 [temp.arg.explicit] /6
如果参数类型不包含参与模板参数推导的模板参数,则将对函数参数执行隐式转换(第 4 条)以将其转换为相应函数参数的类型。
if不应被视为if且仅当,因为它会直接与前面引用的文本相矛盾。