奇怪的编译器错误:无法将参数从'int'转换为'int &&'

use*_*997 20 c++

这到底是怎么回事?
我正在尝试创建一对an int和a string,如果我使用"魔术值"但我似乎无法传递变量,我可以创建该对.

std::vector<std::pair<int, std::string> > num_text;

std::string text = "Smeg";
int num = 42;

// Works fine
num_text.push_back(std::make_pair<int, std::string>(42, std::string("Smeg")));  

// Cannot convert parameter 2 from 'std::string' to 'std::string &&'
num_text.push_back(std::make_pair<int, std::string>(42, text));

// Cannot convert parameter 1 from 'int' to 'int &&'
num_text.push_back(std::make_pair<int, std::string>(num, std::string("Smeg")));

// Cannot convert parameter 1 from 'int' to 'int &&'
num_text.push_back(std::make_pair<int, std::string>(num, text));

// Works fine again
num_text.push_back(std::make_pair<int, std::string>(42, std::string("Smeg")));
Run Code Online (Sandbox Code Playgroud)

我正在使用VS 2012并粘贴了一些用VS 2008编写的代码.无法想象它与它有什么关系,但原始(2008)代码没有问题.

我觉得有点不能训练这里发生的事情,但我能说什么,我只是不明白.

Sha*_*baz 20

参考说:

template< class T1, class T2 >
std::pair<T1,T2> make_pair( T1 t, T2 u );           (until C++11)

template< class T1, class T2 >
std::pair<V1,V2> make_pair( T1&& t, T2&& u );       (since C++11)
Run Code Online (Sandbox Code Playgroud)

请注意,返回类型不同.它还说:

推导出的类型V1和V2是std :: decay :: type和std :: decay :: type(应用于通过value传递的函数的参数的常用类型转换),除非应用std :: decay导致std :: reference_wrapper for某些类型X,在这种情况下推导出的类型是X&.

事实上,自2008年以来(我的意思是Visual C++ 2008),函数的语义make_pair已经发生了变化.您可以从中删除模板参数std::make_pair并让它推断出类型,或者std::pair如果需要创建特定类型的对,则使用构造函数:

num_text.push_back(std::make_pair(num, text));               // deduced type
num_text.push_back(std::pair<int, std::string>(num, text));  // specific type
Run Code Online (Sandbox Code Playgroud)

编译错误的原因是您已指定类型为int(as T1)和std::string(as T2),因此函数期望T1 &&T2 &&.看到这个答案,为什么这是一个问题.


Mik*_*our 15

make_pair<T1,T2>不会生成一对类型pair<T1,T2>,而是从其参数中推导出一对合适的引用类型,以允许完美转发.它被指定为

template <class T1, class T2>
pair<V1, V2> make_pair(T1&& x, T2&& y);
Run Code Online (Sandbox Code Playgroud)

对于一些合适的参考类型V1V2.这仅在推导出参数类型时才有效,因此&&可以在必要时衰减到左值引用.通过显式指定模板参数,不再推导出它们,因此函数参数只能是rvalues.

解决方案是让编译器推导出类型:

num_text.push_back(std::make_pair(42, std::string("Smeg")));  // Works fine
num_text.push_back(std::make_pair(42, text));                 // Works fine
num_text.push_back(std::make_pair(num, std::string("Smeg"))); // Works fine
num_text.push_back(std::make_pair(num, text));                // Works fine
num_text.push_back(std::make_pair(42, std::string("Smeg")));  // Works fine again
Run Code Online (Sandbox Code Playgroud)

如果您需要制作一对特定类型,请不要使用make_pair,只需成对

// Works, but perhaps with more copying than you want.
num_text.push_back(std::pair<int, std::string>(num, text));   
Run Code Online (Sandbox Code Playgroud)


Dan*_*rey 6

make_pair通常在明确指定模板参数的情况下使用.这就是它的用法:

num_text.push_back(std::make_pair(42, std::string("Smeg")));
num_text.push_back(std::make_pair(42, text));
num_text.push_back(std::make_pair(num, std::string("Smeg")));
num_text.push_back(std::make_pair(num, text));
num_text.push_back(std::make_pair(42, std::string("Smeg")));
Run Code Online (Sandbox Code Playgroud)

或者,如果您想要确切的类型:

typedef decltype(num_text)::value_type value_type;
num_text.push_back(value_type(42, std::string("Smeg")));
num_text.push_back(value_type(42, text));
num_text.push_back(value_type(num, std::string("Smeg")));
num_text.push_back(value_type(num, text));
num_text.push_back(value_type(42, std::string("Smeg")));
Run Code Online (Sandbox Code Playgroud)