我试图模仿tie
预C ++ 11的行为。
pair<int, int> test() {
return make_pair(13, 42);
}
int main() {
int a = 1, b = 2;
pair<int&, int&>(a, b) = test();
cout << a << ' ' << b << endl;
}
This works但是,如果我使用make_pair
代替pair
构造函数a
并且未分配b
。
为什么pair
构造函数有效但不是make_pair
?
答案 0 :(得分:3)
实际上你可以使用std::make_pair
。但是你需要实现reference_wrapper
类来模仿参考。示例(非常精细,但按预期工作)c ++ 03方法:
#include <iostream>
#include <utility>
using namespace std;
template <class T>
struct reference_wrapper {
bool is_const;
T* v;
T const* cv;
reference_wrapper(T& t): v(&t), is_const(false) { }
reference_wrapper(T const& t): cv(&t), is_const(true) { }
reference_wrapper &operator=(reference_wrapper const &rw) {
if (rw.is_const) {
*v = *rw.cv;
} else {
*v = *rw.v;
}
}
};
template <class T>
reference_wrapper<T> ref(T &t) {
return reference_wrapper<T>(t);
}
pair<int, int> test() {
return make_pair(13, 42);
}
int main() {
int a = 1, b = 2;
//pair<int&, int&>(a, b) = test(); // works
make_pair(ref(a), ref(b)) = test(); // now it does work
std::cout << a << ' ' << b << std::endl;
}
答案 1 :(得分:3)
在20.2.2 [lib.pairs] 8中,标准规定pair
使用&#34;显式类型&#34;而make_pair
&#34; s&#34;类型被推断出来&#34;。
这就是标准为pair
定义构造函数的原因:
template <class T1, class T2>
pair(const T1& x, const T2& y)
如果您在C++03 compiler上运行代码,则会收到此错误:
非静态引用成员
int& std::pair<int&, int&>::first
,不能使用默认赋值运算符
问题在于,pair
使用的implicitly-declared copy assignment operator如果pair
:
具有引用类型的非静态数据成员
无论是由make_pair
还是pair
构造函数定义,模板参数都会将pair
的成员定义为int&
,因此隐式声明不会定义复制赋值运算符。 因此,使用C ++ 03中的pair
无法实现这一点。
如果不希望使用return参数,您可以编写自己的tie
实现:
template <class T1, class T2>
struct tie{
T1& first;
T2& second;
tie(T1& x, T2& y) : first(x), second(y) {}
tie<T1, T2>& operator=(const pair<T1, T2>& rhs){
first = rhs.first;
second = rhs.second;
return *this;
}
};
这将允许分配pair
:
tie<int, int>(a, b) = test();
要获得不需要模板参数的确切C ++ 11行为,您需要定义一个函数。如果tie
嵌套在namespace details
中,则该函数可以定义为:
template <class T1, class T2>
details::tie<T1, T2> tie(T1& x, T2& y) {
return details::tie<T1, T2>(x, y);
}
这将允许分配pair
,就像在C ++ 11中一样:
tie(a, b) = test();
请注意,这仍然不能容忍使用int&
模板参数,因此details::tie<int&, int&>
和tie<int&, int&>
将会像以前一样失败。
答案 2 :(得分:2)
make_pair
生成一对值,而不是引用。这意味着它会在您的示例中生成pair<int, int>
,并且您将test()
的结果分配给临时变量¹。
您可以使用以下内容模仿tie
:
template<typename T, typename U>
std::pair<T&, U&> tie_pair(T& l, U& r)
{
return std::pair<T&, U&>(l, r);
}
¹这是C ++ 03不具备ref-qualifiers的不幸副作用。在C ++≥11中,您可以删除operator=
的rvalue this
(在非std类中)并使这种情况成为编译器错误而不是无声的惊人行为。