此问题在此处已有答案:
C++11 make_pair with specified template parameters doesn't compile(1个答案)
Weird compiler error: Cannot convert parameter from 'int' to 'int &&'(4个答案)
std::make_pair, c++11 and explicit template parameters [duplicate](2个答案)
15小时前关门了。
GCC和Clang都拒绝编译这个:
#include <string>
#include <utility>
using namespace std;
int main() {
const string s = "12345";
const string& r = s;
auto p = std::make_pair<string, string>(r, r);
}
GCC说:
error: cannot bind rvalue reference of type ‘std::__cxx11::basic_string<char>&&’ to lvalue of type ‘const std::string’ {aka ‘const std::__cxx11::basic_string<char>’}
而Clang说:
error: no matching function for call to 'make_pair'
既然我给make_pair
显式类型,为什么它不从const string&
构造新的字符串?
这一个编译:
auto p = std::make_pair<string, string>(string(r), string(r));
2条答案
按热度按时间vlju58qv1#
假设是C++11或更高版本:
std::make_pair
不应该与显式指定的模板参数一起使用。它们旨在通过转发引用从函数参数推导出来。std::make_pair
的签名是这表明
T1
和T2
被用作转发引用,因此不应该显式指定。(V1
/V2
是通过decay从T1
/T2
计算出来的。)显式指定模板参数会破坏转发行为。使用
string
作为模板参数,您会在函数参数中获得string&&
,这是一个不接受左值的右值引用。您需要提供const string&
作为T
的模板参数,以使T&&
也成为const string&
。但别这样写
如预期用途。
在C++11之前,没有转发引用,
std::make_pair
看起来像这样:所以你的问题中的代码可以在C++11之前编译。尽管如此,指定模板参数也是多余的。
g52tjvyc2#
根据pairs.spec,
make_pair
的定义如下:并返回:
unwrap_ref_decay_t在这里就是
std::decay_t
,因为你没有使用reference_wrapper
(而std::decay<string>
就是string
)。因此,当你显式地命名你的模板参数时,你最终会得到这样的签名:看看函数参数是如何从“转发引用”(
T&&
)变成r值引用(string&&
)的?因为你提供了
const string&
参数,它们不能被转换,因此编译失败。这就是为什么当你显式传递string(r)
时,它开始工作。解决方案是不像user17732522所说的那样传递类型参数