Im finding a bug between debug and release builds of the following code.
#include <vector>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/range/adaptors.hpp>
using namespace std;
namespace br = boost::range;
namespace badpt = boost::adaptors;
std::pair<int,int> pr_swap(std::pair<int,int> pr)
{return make_pair(pr.second,pr.first);}
int main()
{
std::vector<pair<int,int> > vec;
vec.push_back(make_pair(1,2));
vec.push_back(make_pair(2,1));
br::copy(vec|badpt::transformed(bind(pr_swap,_1))|badpt::map_keys,std::ostream_iterator<int>(cout," "));
}
With, gcc-4.8.1 -O3, I get
0 0
And without I get as expected
2,1
Any ideas what is going wrong?
I ran into this problem recently.
The implementation of select_first (i.e. which is used by map_keys) in boost/range/adaptor/map.hpp returns a reference. The output of the pr_swap function returns a value. This is undefined behavior, which typically is only exposed when compiler optimizations are enabled.
I do not know why the compiler failed to emit a return-local-addr warning.
I got around the problem in the following manner:
#include <iostream>
#include <vector>
#include "boost/range/algorithm.hpp"
#include "boost/range/adaptors.hpp"
int main()
{
const std::vector<std::pair<int, int>> v{{1,2},{3,4},{5,6}};
auto swap = [](const auto& p) { return std::make_pair(p.second, p.first); };
auto getFirst = [](const auto& p) { return p.first; };
auto rng = v | boost::adaptors::transformed(swap) | boost::adaptors::transformed(getFirst);
boost::copy(rng, std::ostream_iterator<int>(std::cout, ", "));
return 0;
}
Related
I have a member variable that stores a std::shared_ptr of std::vector<uint32_t>. I want to create a Python binding for test_func2() so that I can access that vector without any additional copy. Here is a skeleton code.
#include <vector>
#include <memory>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/numpy.h>
namespace py = pybind11;
class TestLoader
{
private:
std::shared_ptr<std::vector<uint32_t>> tileData;
public:
TestLoader();
~TestLoader();
void test_func1();
std::shared_ptr<std::vector<uint32_t>> test_func2() const;
};
void TestLoader::test_func1() {
tileData = std::make_shared<std::vector<uint32_t>>(100000000);
for(auto &x: *tileData){ x = 1;}
}
std::shared_ptr<std::vector<uint32_t>> TestLoader::test_func2() const{
return tileData;
}
The interface code is like the following:
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
namespace py = pybind11;
PYBIND11_MODULE(fltest_lib, m) {
py::class_<TestLoader, std::shared_ptr<TestLoader>>(m, "TestLoader")
.def(py::init<const std::string &>())
.def("test_func1", &TestLoader::test_func1)
.def("test_func2", &TestLoader::test_func2, py::return_value_policy::reference_internal);
}
However, this does not compile and I get a long error message. One particular line is the following:
/home/samee/fl_test/lib/pybind11/include/pybind11/cast.h:653:61: error: static assertion failed: Holder classes are only supported for custom types
653 | static_assert(std::is_base_of<base, type_caster<type>>::value,
| ^~~~~
Any help to circumvent this will be really helpful.
According to this issue, it doesn't work because std::vector<uint32_t> is not converted to a python type. So, you will have to return the dereferenced vector. To avoid copies, you can use PYBIND11_MAKE_OPAQUE
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/stl_bind.h>
#include "test_loader.h"
namespace py = pybind11;
PYBIND11_MAKE_OPAQUE(std::vector<uint32_t>);
PYBIND11_MODULE(fltest_lib, m) {
py::bind_vector<std::vector<uint32_t>>(m, "VectorUInt32");
py::class_<TestLoader, std::shared_ptr<TestLoader>>(m, "TestLoader")
.def(py::init())
.def("test_func1", &TestLoader::test_func1)
.def("test_func2",
[](const TestLoader& tl) -> const std::vector<uint32_t>& {
return *tl.test_func2();
}, py::return_value_policy::reference_internal);
}
I want to pass cv::cuda::GpuMat to thrust function and I find this function which can be used for creating a thrust iterator that indexes a cv::cuda::GpuMat. I have 2 problems in the following code:
#include <stdio.h>
#include<io.h>
#include <stdlib.h>
#include <fstream>
#include<string>
#include<iostream>
#include <time.h>
#include <vector>
#include <cuda_runtime.h>
#include "device_launch_parameters.h"
#include <thrust/host_vector.h>
#include<thrust/functional.h>
#include <thrust/device_vector.h>
#include <thrust/generate.h>
#include <thrust/sort.h>
#include <thrust/copy.h>
#include<opencv2/opencv.hpp>
#include<cudaimgproc.hpp>
#include<opencv2/cudafilters.hpp>
#include<opencv2/cudaarithm.hpp>
template<typename T>
struct greater_than_value_pred
{
T value;
greater_than_value_pred(T value) : value(value) {}
__host__ __device__
bool operator()(T v) const { return v > value; }
};
using namespace std;
int main()
{
int compare_vari = 20;
cv::cuda::GpuMat d_data_open(1, 100, CV_32SC2);
// Thrust compatible begin and end iterators to channel 0 of this matrix
auto idxBegin = GpuMatBeginItr<int>(d_data_open, 1);
auto idxEnd = GpuMatEndItr<int>(d_data_open, 1);
// Fill the index channel with a sequence of numbers from 0 to 100
thrust::sequence(idxBegin, idxEnd);
d_iter = thrust::find_if(idxBegin, idxEnd, greater_than_value_pred<int>(compare_vari));
/*Use thrust::device_data to test */
thrust::device_vector<int> d_thrust_data;
thrust::device_vector<int>::iterator d_iter;
thrust::sequence(d_thrust_data.begin(), d_thrust_data.end());
d_iter = thrust::find_if(d_thrust_data.begin(), d_thrust_data.end(), greater_than_value_pred<int>(compare_vari));
//std::cout << *d_iter << std::endl;
}
Question 1:
This code cannot complie: d_iter = thrust::find_if(idxBegin, idxEnd, greater_than_value_pred<double>(compare_vari));
Using idxBegin and idxEnd works well with thrust::sequence(), sort() and so on, but when applying them to thrust::find_if(), it will hint "no operator '=' matches these operands".
Question 2:
*//std::cout << *d_iter << std::endl;*
I want to check the result by the above code, but when debugging it says abort() has been called. I wonder if d_iter is in device memory, if so I need to copy it to host memory? But I don't know how to copy iterator to the host memory.
Any help will be appreciated.
Question 2:
*//std::cout << d_iter << std::endl;
I want to check the result by the above code, but when debugging it says abort() has been called. I wonder if d_iter is in device memory, if so I need to copy it to host memory? But I don't know how to copy iterator to the host memory.
(You don't want to copy the iterator to host memory, what you desire is to copy what the iterator points to to host memory.)
The issue here is that you are not giving any actual size to the device_vector in question:
thrust::device_vector<int> d_thrust_data;
that creates an empty vector with no allocation. Therefore no iterator referencing that vector will point to anything valid, because there is no allocation associated with that vector. If we modify it to:
thrust::device_vector<int> d_thrust_data(22);
we have now created a vector with 22 elements, and the rest of your code, including your std::cout ... statement, will then be sensible. (21 or larger is also important because your find_if is looking for an element of value 20.)
The following code has the above issues addressed and seems to compile and run correctly for me:
$ cat t100.cu
#include <stdio.h>
#include <stdlib.h>
#include <thrust/host_vector.h>
#include <thrust/functional.h>
#include <thrust/device_vector.h>
#include <thrust/generate.h>
#include <thrust/sort.h>
#include <thrust/copy.h>
template<typename T>
struct greater_than_value_pred
{
T value;
greater_than_value_pred(T value) : value(value) {}
__host__ __device__
bool operator()(T v) const { return v > value; }
};
using namespace std;
int main()
{
int compare_vari = 20;
/*Use thrust::device_data to test */
thrust::device_vector<int> d_thrust_data(22);
thrust::device_vector<int>::iterator d_iter;
thrust::sequence(d_thrust_data.begin(), d_thrust_data.end());
d_iter = thrust::find_if(d_thrust_data.begin(), d_thrust_data.end(), greater_than_value_pred<int>(compare_vari));
std::cout << *d_iter << std::endl;
}
$ nvcc -o t100 t100.cu
$ ./t100
21
$
I'm using boost 1.52 and Visual Studio 2010.
I'm wondering why I can't enforce on the elements returned by boost::adaptors::indirected.
This sample code shows what I'm trying to achieve:
#include <vector>
#include <string>
#include <boost/range/adaptor/indirected.hpp>
#include <boost/foreach.hpp>
int main() {
using std::vector;
using std::string;
typedef vector<string*> type;
type range;
range.push_back(new string("42"));
type const& const_range = range;
// This is ok to compile
BOOST_FOREACH(string const& foo, const_range | boost::adaptors::indirected) {
//...
}
// I don't want this to compile
BOOST_FOREACH(string& foo, const_range | boost::adaptors::indirected) {
//...
}
return 0;
}
Given a multimap<A,B> M what's a neat way to create a vector<B> of all values in M with a specific key.
e.g given a multimap how can I get a vector of all strings mapped to the value 123?
An answer is easy, looping from lower->upper bound, but is there a neat loop-free method?
Here's the way to do it STL style :
// The following define is needed for select2nd with DinkumWare STL under VC++
#define _HAS_TRADITIONAL_STL 1
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <functional>
#include <map>
#include <iterator>
#include <iostream>
using namespace std;
void main()
{
typedef multimap<string, int> MapType;
MapType m;
vector<int> v;
// Test data
for(int i = 0; i < 10; ++i)
{
m.insert(make_pair("123", i * 2));
m.insert(make_pair("12", i));
}
MapType::iterator i = m.lower_bound("123");
MapType::iterator j = m.upper_bound("123");
transform(i, j, back_inserter(v), select2nd<MapType::value_type>());
copy(v.begin(), v.end(), ostream_iterator<int>(cout, ","));
}
Let's go lambda
given: multimap<A,B> M
requested: vector<B> (of all values in M with a specific key 'a'.)
method:
std::pair<M::iterator, M::iterator> aRange = M.equal_range('a')
std::vector<B> aVector;
std::transform(aRange.first, aRange.second,std::back_inserter(aVector), [](std::pair<A,B> element){return element.second;});
System environment:
compiler: gcc (Ubuntu 5.3.1-14ubuntu2.1) 5.3.1 20160413 (with -std=c++11)
os: ubuntu 16.04
Code example:
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <functional>
#include <iostream>
int main()
{
typedef std::multimap<std::string, int> MapType;
MapType m;
std::vector<int> v;
/// Test data
for(int i = 0; i < 10; ++i)
{
m.insert(std::make_pair("123", i * 2));
m.insert(std::make_pair("12", i));
}
std::pair<MapType::iterator,MapType::iterator> aRange = m.equal_range("123");
std::transform(aRange.first, aRange.second, std::back_inserter(v), [](std::pair<std::string,int> element){return element.second;});
for(auto & elem: v)
{
std::cout << elem << std::endl;
}
return 0;
}
You need a loop anyway. All "loop-free" methods just abstract the loop away.
#include <map>
#include <vector>
#include <algorithm>
#include <ext/functional>
using namespace std;
int main () {
multimap<int, double> mm;
mm.insert(make_pair(1, 2.2));
mm.insert(make_pair(4, 2.6));
mm.insert(make_pair(1, 9.1));
mm.insert(make_pair(1, 3.1));
vector<double> v;
transform(mm.lower_bound(1), mm.upper_bound(1),
back_inserter(v), __gnu_cxx::select2nd<pair<int, double> >());
// note: select2nd is an SGI extension.
for (vector<double>::const_iterator cit = v.begin(); cit != v.end(); ++ cit)
printf("%g, ", *cit); // verify that you've got 2.2, 9.1, 3.1
return 0;
}
template <class Key, class Val>
vector<Val>& getValues(multimap<Key, Val>& multi, Key& key)
{
typedef multimap<Key, Val>::iterator imm;
static vector<Val> vect;
static struct
{
void operator()(const pair<Key, Val>& p) const
{
vect.push_back(p.second);
}
} Push;
vect.clear();
pair<imm, imm> range = multi.equal_range(key);
for_each(range.first, range.second, Push);
return vect;
}
This is a bit contrived because of your 'no loop' requirement.
I prefer:
template <class Key, class Val>
vector<Val> getValues(multimap<Key, Val>& map, Key& key)
{
vector<Val> result;
typedef multimap<Key, Val>::iterator imm;
pair<imm, imm> range = map.equal_range(key);
for (imm i = range.first; i != range.second; ++i)
result.push_back(i->second);
return result;
}
You could initialise the vector by giving it two iterators, like this:
std::multimap<std::string, std::string> bar;
...
std::vector<pair<string,string> > foo(bar.lower_bound("123"), bar.upper_bound("123"));
but that would give you a vector of pairs (ie, with both the key and value).
Another option would be to use std::copy with something like a back_inserter, which is another way to hide the loop, but with the same downside as above.
std::copy(bar.lower_bound("123"), bar.upper_bound("123"), std::back_inserter(foo));
This would append the elements (if any) to the vector foo.
For extracting the values only, I can't think of any way but to loop over the results as I'm not aware of a standard way to get only the value out of a range.
Just some addenda to the other answers hereā¦
std::mem_fn (from #include <functional>) can be used as a shorthand for the transform operator:
// previously we might've used this longhand
[](pair<int,string> element){return element.second;}
And we can use vector::resize and std::distance to allocate space for the vector in one go, rather than repeatedly resizing it with back_inserter.
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <functional>
#include <iterator>
#include <iostream>
using namespace std;
typedef multimap<int, string> MapType;
int main()
{
MapType multimap;
vector<string> valuesForKey123;
multimap.emplace(0, "red");
multimap.emplace(123, "hello");
multimap.emplace(123, "world");
multimap.emplace(0, "herring");
MapType::iterator lower{multimap.lower_bound(123)};
MapType::iterator upper{multimap.upper_bound(123)};
valuesForKey123.resize(distance(lower, upper));
transform(
lower,
upper,
valuesForKey123.begin(),
mem_fn(&MapType::value_type::second));
copy(
valuesForKey123.begin(),
valuesForKey123.end(),
ostream_iterator<string>(cout, " "));
}
// outputs "hello world "
Say there is a list of integers [1,2,3,4,5] and a map function that multiplies each element with 10 and returns modified list as [10,20,30,40,50] , with out modifying the original list.
How this can be done efficiently in c++.
Here's an example:
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int multiply(int);
int main() {
vector<int> source;
for(int i = 1; i <= 5; i++) {
source.push_back(i);
}
vector<int> result;
result.resize(source.size());
transform(source.begin(), source.end(), result.begin(), multiply);
for(vector<int>::iterator it = result.begin(); it != result.end(); ++it) {
cout << *it << endl;
}
}
int multiply(int value) {
return value * 10;
}
Along the lines of #darids answer, but C++03 (current at the time of original post):
#include <vector>
#include <algorithm>
#include <functional>
std::vector<int> src;
std::vector<int> dst;
std::transform(src.begin(), src.end(),
std::back_inserter(dst),
std::bind1st(std::multiplies<int>(), 10));
If you can use it, probably the best idea is to use a function in the Standard Template Library.
For example, you might want to check out for_each or transform, which basically do just that.
I only post this to illustrate using a functor in transform rather than a global function:
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <functional>
#include <iostream>
using namespace std;
struct MulBy : public std::unary_function<int, int>
{
MulBy(int v) : v_(v) {}
int operator()(int lhs) const
{
return lhs * v_;
}
private:
int v_;
};
int main()
{
int incoming[5] = {1, 2, 3, 4, 5};
int result[5] = {0, 0, 0, 0, 0};
transform(&incoming[0], &incoming[5], &result[0], MulBy(10));
copy(&result[0], &result[5], ostream_iterator<int>(cout, " "));
return 0;
}
#include <iostream>
#include <algorithm>
#include <vector>
#include <functional>
using namespace std;
struct MulBy : public std::unary_function<int, int>
{
MulBy(int v) : v_(v) {}
int operator()(int lhs) const
{
return lhs * v_;
}
private:
int v_;
};
int main()
{
vector<int> ListOfNumber;
ListOfNumber.push_back(1);
ListOfNumber.push_back(2);
ListOfNumber.push_back(3);
ListOfNumber.push_back(4);
ListOfNumber.push_back(5);
vector<int> ListResult;
ListResult.resize(ListOfNumber.size());
//Produces a new list
transform(ListOfNumber.begin(),ListOfNumber.end(),ListResult.begin(),MulBy(10));
copy(ListOfNumber.begin(),ListOfNumber.end(),ostream_iterator<int>(cout,"\t"));
//Modifies the original list
transform(ListOfNumber.begin(),ListOfNumber.end(),ListOfNumber.begin(),MulBy(10));
copy(ListResult.begin(),ListResult.end(),ostream_iterator<int>(cout,"\t"));
cin.get();
}
This is my implementation for an array map method, inspired directly from javascript
#include <vector>
#include <functional>
namespace wh{
namespace array{
template<typename T>
std::vector<T> map(const std::vector<T> &vectorToMap, const std::function<T(T)> &functor){
std::vector<T> ret;
for(auto &element: vectorToMap){
ret.push_back(functor(element));
}
return ret;
}
...
}
}
#include <iostream>
int main()
{
//'spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'
std::vector<std::string> words = {"spray", "limit", "elite", "exuberant", "destruction", "present", "windows", "wlol"};}
// and this is how it is used:
words = wh::array::map<std::string>(words, [](auto word){return word+"l";});
for(auto &word: words) std::cout << word << std::endl;
return 0;
}
Maybe this will be useful for someone else, still, if <algorithm> functions are a better approach, go ahead and use them.