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

时间:2022-03-25 21:17:26

What on earth is going on here?
I'm trying to create a pair of an int and a string and I can create the pair if I use "magic values" but can't seem to pass in variables.

到底是怎么回事?我正在尝试创建一对int和一个字符串,如果我使用“魔术值”但我似乎无法传递变量,我可以创建该对。

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

I am using VS 2012 and have pasted in some code that was written in VS 2008. Can't imagine that would have anything to do with it but there was no problem in the original (2008) code.

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

I kind of feel a bit dumb for not being able to workout what is going on here but what can I say, I just don't get it.

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

4 个解决方案

#1


18  

Reference says:

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)

Note that the return type is different. It also says:

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

The deduced types V1 and V2 are std::decay::type and std::decay::type (the usual type transformations applied to arguments of functions passed by value) unless application of std::decay results in std::reference_wrapper for some type X, in which case the deduced type is X&.

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

So in fact, since 2008 (I mean Visual C++ 2008), the semantics of the function make_pair has changed. You could either remove the template parameters from std::make_pair and let it deduce the type, or use std::pair's constructor if you need to make pairs of specific type:

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

The reason for the compile error is that you have specified the types to be int (as T1) and std::string (as T2), and therefore the function expects T1 && and T2 &&. See this answer for why that's a problem.

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

#2


14  

make_pair<T1,T2> does not make a pair of type pair<T1,T2>, but rather deduces a suitable pair of reference types from its arguments to allow perfect forwarding. It's specified as

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

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

for some suitable reference types V1 and V2. This only works if the argument types are deduced, so that && can decay to an lvalue reference if necessary. By specifying the template parameters explicitly, they are no longer deduced, and so the function arguments can only be rvalues.

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

The solution is to let the compiler deduce the types:

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

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

If you need to make a pair of a particular type, don't use make_pair, just make a pair

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

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

#3


6  

make_pair is usually used without specifying the template parameters explicitly. This is how it is meant to be used:

通常使用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")));

Alternatively, if you want the exact type:

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

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

#4


2  

Now std::make_pair is defined the following way in the C++ Standard

现在,在C ++标准中,std :: make_pair的定义方式如下

template <class T1, class T2>

see below make_pair(**T1&&, T2&&**);

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

You could write simpler without using std::make_pair

你可以在不使用std :: make_pair的情况下编写更简单的东西

num_text.push_back( { 42, text } ); .

num_text.push_back({42,text}); 。

#1


18  

Reference says:

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)

Note that the return type is different. It also says:

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

The deduced types V1 and V2 are std::decay::type and std::decay::type (the usual type transformations applied to arguments of functions passed by value) unless application of std::decay results in std::reference_wrapper for some type X, in which case the deduced type is X&.

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

So in fact, since 2008 (I mean Visual C++ 2008), the semantics of the function make_pair has changed. You could either remove the template parameters from std::make_pair and let it deduce the type, or use std::pair's constructor if you need to make pairs of specific type:

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

The reason for the compile error is that you have specified the types to be int (as T1) and std::string (as T2), and therefore the function expects T1 && and T2 &&. See this answer for why that's a problem.

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

#2


14  

make_pair<T1,T2> does not make a pair of type pair<T1,T2>, but rather deduces a suitable pair of reference types from its arguments to allow perfect forwarding. It's specified as

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

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

for some suitable reference types V1 and V2. This only works if the argument types are deduced, so that && can decay to an lvalue reference if necessary. By specifying the template parameters explicitly, they are no longer deduced, and so the function arguments can only be rvalues.

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

The solution is to let the compiler deduce the types:

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

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

If you need to make a pair of a particular type, don't use make_pair, just make a pair

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

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

#3


6  

make_pair is usually used without specifying the template parameters explicitly. This is how it is meant to be used:

通常使用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")));

Alternatively, if you want the exact type:

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

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

#4


2  

Now std::make_pair is defined the following way in the C++ Standard

现在,在C ++标准中,std :: make_pair的定义方式如下

template <class T1, class T2>

see below make_pair(**T1&&, T2&&**);

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

You could write simpler without using std::make_pair

你可以在不使用std :: make_pair的情况下编写更简单的东西

num_text.push_back( { 42, text } ); .

num_text.push_back({42,text}); 。