首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >添加对boost::fusion::vector的引用

添加对boost::fusion::vector的引用
EN

Stack Overflow用户
提问于 2013-01-13 23:00:38
回答 1查看 540关注 0票数 2

我想创建一个引用变量的boost融合向量。目标是将不同数量的参数传递给函数,并将它们添加到融合向量中。由于引用类型,我使用TMP一次添加一个元素。但有时融合向量中的某些元素是错误的。这看起来像是未定义的行为(错误的值,读访问冲突)。

我写了一个例子,为了更容易理解,我“展开”了TMP中使用的递归。它只需将两个引用添加到融合向量中并输出结果:

代码语言:javascript
复制
#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融合向量中的引用被访问(读访问冲突)时,程序崩溃,第一行:

代码语言:javascript
复制
std::cout << at_c<0>(ret) << std::endl;

我使用VC11作为编译器(版本17.00.51106.1)。仅在释放模式下出现错误。但当我使用VC10,GCC 4.7.0或GCC 4.7.2没有错误,程序运行得很好。

要使程序与VC11一起工作,我必须更改这一行

代码语言:javascript
复制
auto newVector = join(vec, make_vector(ref(v1)));

代码语言:javascript
复制
auto newVector = as_vector(join(vec, make_vector(ref(v1))));

那么,上面的示例是否包含错误,或者VC11优化器有什么问题呢?允许通过值将本地boost融合视图(boost:: fusion ::join仅返回一个视图,该视图通过boost::fusion::vector转换为'normal‘boost::fusion::vector)传递给另一个函数吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-04-18 15:01:12

我在微软连接(link)上提交了一份bug报告。所以我的问题的答案是我的代码中有一个bug。

问题是join函数返回一个boost融合joint_view,其中包含两个元素seq1和seq2。它们被定义为:

代码语言:javascript
复制
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,这是无效的。有两个修改可以解决这个问题:

  1. First解决方案(与createVector相同):

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.

  • Second解决方案(与createVector相同):

template vector

临时对象(由make_vector返回)的生存期是整个返回语句,与第一个版本一样,视图将转换为boost融合向量,并再次解析引用。

感谢Eric Brumer (Microsoft),他提供了这两个解决方案。

结论:不要将临时对象传递给boost融合连接函数(仅当它是另一个视图时)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14304688

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档