如何在同时使用 boost compute 和 boost::range 时避免 boost::compute::zip_iterator 和 boost::iterators::zip_iterator 冲突?

How can I avoid the boost::compute::zip_iterator and boost::iterators::zip_iterator confict when using boost compute and boost::range together?

我想一起使用 boost::compute and boost::range,如下所示,但是如果我取消注释 #include <boost/range/combine.hpp> 行,我会收到一条错误消息,指出 boost::compute::zip_iteratorboost::iterators::zip_iterator 是模糊的。有没有办法解决这个问题,以便我可以在同一个 cpp 文件中同时使用 boost::computeboost::range?我在 Windows vs2015 64 位上使用。提升 1.67.0.

更新:我发现如果我尝试包含 boost/iterator/zip_iterator.hpp 而不是 boost/range/combine.hpp,也会发生同样的错误,所以它不是特定于 Boost Range 库。

代码:

#include <vector>
#include <iostream>
#include <algorithm>
//#include <boost/range/combine.hpp>
#include <boost/compute/lambda.hpp>
#include <boost/compute/functional/math.hpp>
#include <boost/compute/container/vector.hpp>
#include <boost/compute/algorithm/transform.hpp>

namespace compute = boost::compute;
using compute::float4_;
using compute::lambda::_1;
using compute::lambda::_2;
using compute::lambda::distance;

int main()
{
    // get default device and setup context
    compute::device device = compute::system::default_device();
    compute::context context(device);
    compute::command_queue queue(context, device);

    // generate random data on the host
    std::vector<float4_> a(10000);
    std::vector<float4_> b(10000);
    std::vector<float> r(10000);
    std::generate((float*)a.data(), (float*)(a.data() + a.size()), rand);
    std::generate((float*)b.data(), (float*)(b.data() + b.size()), rand);

    // create a vector on the device
    compute::vector<float4_> _a(a.size(), context);
    compute::vector<float4_> _b(b.size(), context);
    compute::vector<float> _r(r.size(), context);

    // transfer data from the host to the device
    compute::copy(a.begin(), a.end(), _a.begin(), queue);
    compute::copy(b.begin(), b.end(), _b.begin(), queue);

    boost::compute::transform(
        _a.begin(), _a.end(),
        _b.begin(),
        _r.begin(),
        distance(_1, _2),
        queue
    );

    // copy values back to the host
    compute::copy(_r.begin(), _r.end(), r.begin(), queue);

    for (int i = 0; i < a.size(); ++i)
    {
        float4_ va = a[i];
        float4_ vb = b[i];
        float vr = r[i];
        float e = std::sqrt(std::pow(va[0] - vb[0], 2) +
            std::pow(va[1] - vb[1], 2) +
            std::pow(va[2] - vb[2], 2) +
            std::pow(va[3] - vb[3], 2));

        std::cout << std::setprecision(12);

        if (std::abs(e - vr) > 1e-2)
            std::cout << e << " != " << vr << "\n";
    }

    return 0;
}

错误:

1>------ Build started: Project: demo, Configuration: Debug x64 ------ 1> demo.cpp 1> This header is implementation detail and provided for backwards compatibility. 1>C:\local\boost_1_67_0\boost/compute/algorithm/transform.hpp(67): error C2668: 'boost::compute::make_zip_iterator': ambiguous call to overloaded function 1> C:\local\boost_1_67_0\boost/compute/iterator/zip_iterator.hpp(276): note: could be 'boost::compute::zip_iterator,boost::compute::buffer_iterator,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>> boost::compute::make_zip_iterator,boost::compute::buffer_iterator,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>>(IteratorTuple)' 1> with 1> [ 1>
T=boost::compute::float4_, 1>
IteratorTuple=boost::tuples::tuple,boost::compute::buffer_iterator,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type> 1> ] 1> C:\local\boost_1_67_0\boost/iterator/zip_iterator.hpp(357): note: or
'boost::iterators::zip_iterator,boost::compute::buffer_iterator,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>> boost::iterators::make_zip_iterator,boost::compute::buffer_iterator,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>>(IteratorTuple)' [found using argument-dependent lookup] 1> with 1> [ 1> T=boost::compute::float4_, 1>
IteratorTuple=boost::tuples::tuple,boost::compute::buffer_iterator,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type> 1> ] 1> C:\local\boost_1_67_0\boost/compute/algorithm/transform.hpp(67): note: while trying to match the argument list '(boost::tuples::tuple,boost::compute::buffer_iterator,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>)' 1> with 1> [ 1>
T=boost::compute::float4_ 1> ] 1> C:\workspaces\compute_test\src\demo.cpp(45): note: see reference to function template instantiation 'OutputIterator boost::compute::transform,boost::compute::buffer_iterator,boost::compute::buffer_iterator,boost::compute::lambda::expression>(InputIterator1,InputIterator1,InputIterator2,OutputIterator,BinaryOperator,boost::compute::command_queue &)' being compiled 1> with 1> [ 1>
OutputIterator=boost::compute::buffer_iterator, 1>
T=boost::compute::float4_, 1>
Expr=boost::proto::exprns_::basic_expr,0>>,const boost::compute::lambda::expression>,0>> &,const boost::compute::lambda::expression>,0>> &>,3>, 1>
InputIterator1=boost::compute::buffer_iterator, 1>
InputIterator2=boost::compute::buffer_iterator, 1>
BinaryOperator=boost::compute::lambda::expression,0>>,const boost::compute::lambda::expression>,0>> &,const boost::compute::lambda::expression>,0>> &>,3>> 1> ] 1>C:\local\boost_1_67_0\boost/compute/algorithm/transform.hpp(68): error C2668: 'boost::compute::make_zip_iterator': ambiguous call to overloaded function 1> C:\local\boost_1_67_0\boost/compute/iterator/zip_iterator.hpp(276): note: could be 'boost::compute::zip_iterator,boost::compute::buffer_iterator,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>> boost::compute::make_zip_iterator,boost::compute::buffer_iterator,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>>(IteratorTuple)' 1> with 1> [ 1>
T=boost::compute::float4_, 1>
IteratorTuple=boost::tuples::tuple,boost::compute::buffer_iterator,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type> 1> ] 1> C:\local\boost_1_67_0\boost/iterator/zip_iterator.hpp(357): note: or
'boost::iterators::zip_iterator,boost::compute::buffer_iterator,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>> boost::iterators::make_zip_iterator,boost::compute::buffer_iterator,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>>(IteratorTuple)' [found using argument-dependent lookup] 1> with 1> [ 1> T=boost::compute::float4_, 1>
IteratorTuple=boost::tuples::tuple,boost::compute::buffer_iterator,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type> 1> ] 1> C:\local\boost_1_67_0\boost/compute/algorithm/transform.hpp(68): note: while trying to match the argument list '(boost::tuples::tuple,boost::compute::buffer_iterator,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>)' 1> with 1> [ 1>
T=boost::compute::float4_ 1> ] 1>C:\local\boost_1_67_0\boost/compute/algorithm/transform.hpp(72): error C2672: 'transform': no matching overloaded function found 1>C:\local\boost_1_67_0\boost/compute/algorithm/transform.hpp(72): error C2780: 'OutputIterator boost::compute::transform(InputIterator1,InputIterator1,InputIterator2,OutputIterator,BinaryOperator,boost::compute::command_queue &)': expects 6 arguments - 4 provided 1> C:\local\boost_1_67_0\boost/compute/algorithm/transform.hpp(55): note: see declaration of 'boost::compute::transform' ========== Build: 0 succeeded,

1 failed, 2 up-to-date, 0 skipped ==========

短期修复是修改 boost/compute/algorithm/transform.hpp。将对 make_zip_iterator 的两个调用更改为 ::boost::compute::make_zip_iterator。这限定了避免参数依赖查找的调用。

更新:这已在 #790

中修复