我想创建一个引用变量的boost融合向量。目标是将不同数量的参数传递给函数,并将它们添加到融合向量中。由于引用类型,我使用TMP一次添加一个元素。但有时融合向量中的某些元素是错误的。这看起来像是未定义的行为(错误的值,读访问冲突)。
我写了一个例子,为了更容易理解,我“展开”了TMP中使用的递归。它只需将两个引用添加到融合向量中并输出结果:
#include <iostream>
#include <boost/ref.hpp>
#include <boost/fusion/algorithm.hpp>
#include <boost/fusion/container.hpp>
using namespace boost;
using namespace boost::fusion;
//add second element
template <typename T>
vector<int&, double&> createVector2(T vec, double& v2) {
auto newVector = join(vec, make_vector(ref(v2)));
return newVector;
}
//add first element
template <typename T>
vector<int&, double&> createVector(T vec, int& v1, double& v2) {
auto newVector = join(vec, make_vector(ref(v1)));
return createVector2(newVector, v2);
}
int main() {
int v1 = 10;
double v2 = 15.3;
vector<> vec;
auto ret = createVector(vec, v1, v2);
std::cout << at_c<0>(ret) << std::endl;
std::cout << at_c<1>(ret) << std::endl;
if (at_c<0>(ret) != v1) {
std::cout << "FAILED" << std::endl;
}
if (at_c<1>(ret) != v2) {
std::cout << "FAILED" << std::endl;
}
return 0;
}当boost融合向量中的引用被访问(读访问冲突)时,程序崩溃,第一行:
std::cout << at_c<0>(ret) << std::endl;我使用VC11作为编译器(版本17.00.51106.1)。仅在释放模式下出现错误。但当我使用VC10,GCC 4.7.0或GCC 4.7.2没有错误,程序运行得很好。
要使程序与VC11一起工作,我必须更改这一行
auto newVector = join(vec, make_vector(ref(v1)));至
auto newVector = as_vector(join(vec, make_vector(ref(v1))));那么,上面的示例是否包含错误,或者VC11优化器有什么问题呢?允许通过值将本地boost融合视图(boost:: fusion ::join仅返回一个视图,该视图通过boost::fusion::vector转换为'normal‘boost::fusion::vector)传递给另一个函数吗?
发布于 2013-04-18 15:01:12
我在微软连接(link)上提交了一份bug报告。所以我的问题的答案是我的代码中有一个bug。
问题是join函数返回一个boost融合joint_view,其中包含两个元素seq1和seq2。它们被定义为:
template <typename Sequence1, typename Sequence2>
struct joint_view : sequence_base<joint_view<Sequence1, Sequence2> >
{
(...)
private:
typename mpl::if_<traits::is_view<Sequence1>, Sequence1, Sequence1&>::type seq1;
typename mpl::if_<traits::is_view<Sequence2>, Sequence2, Sequence2&>::type seq2;
};我的代码的问题在于,我向连接函数传递了一个临时对象(从make_vector返回)。boost融合载体不是视图,seq1和seq2是参考。因此,join函数返回一个包含对临时对象的引用的joint_view,这是无效的。有两个修改可以解决这个问题:
template vector createVector2(T vec,double& v2) { auto x= make_vector(ref(v2));auto newVector = join(vec,x);return newVector;}
现在join返回一个joint_view,其中包含对x的引用,这是有效的。最后,视图转换为boost融合向量,引用为resolved.
template vector
临时对象(由make_vector返回)的生存期是整个返回语句,与第一个版本一样,视图将转换为boost融合向量,并再次解析引用。
感谢Eric Brumer (Microsoft),他提供了这两个解决方案。
结论:不要将临时对象传递给boost融合连接函数(仅当它是另一个视图时)。
https://stackoverflow.com/questions/14304688
复制相似问题