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

时间:2013-10-14 10:30:00

标签: c++

这里到底发生了什么? 我正在尝试创建一对intstring,如果我使用“魔术值”但我似乎无法传递变量,我可以创建该对。

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")));

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

我觉得因为没有能够锻炼这里发生的事情而感到有点愚蠢但是我能说什么,我只是不明白。

4 个答案:

答案 0 :(得分:20)

Reference说:

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)

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

  

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

事实上,自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

编译错误的原因是您已将类型指定为int(作为T1)和std::string(作为T2),因此指定了函数预计T1 &&T2 &&。请参阅this answer了解这是一个问题的原因。

答案 1 :(得分:15)

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

template <class T1, class T2>
pair<V1, V2> make_pair(T1&& x, T2&& y);

适用于某些合适的参考类型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

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

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

答案 2 :(得分: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")));

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

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")));

答案 3 :(得分:2)

现在{C}标准中的std::make_pair定义如下:

template <class T1, class T2>

见下文make_pair(**T1&&, T2&&**);

您可以在不使用std::make_pair

的情况下编写更简单的内容

num_text.push_back( { 42, text } );