Enforce constness using boost::adaptors::indirected - c++

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;
}

Related

pybind11 - Return a shared_ptr of std::vector

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);
}

Trouble returning an object from a class I created

I have this class (hashMap.h):
#pragma once
#include <iostream>
#include <vector>
#include <string>
#include "functions.h"
using std::cout;
using std::vector;
using std::endl;
using std::string;
class hashMap
{
public:
explicit hashMap(int hashEntrySize = 101) : hashVector(nextPrime(2 * hashEntrySize)), currentSize{ 0 }
{}
bool containsKey(const string & searchKey);
bool containsVector(const vector<string> searchVector);
void insert(const string & keyTarget, const vector<string> & insertVector);
void insertAfterReHash(const string & keyTarget, const vector<string> & insertVector);
int getCurrentSize() const;
void assignKey(string & newKey);
private:
enum EntryType { ACTIVE, EMPTY, DELETED };
struct hashEntry
{
vector<string> vectorValue;
EntryType status;
int keyID;
string key;
hashEntry(EntryType s = EMPTY)
:status(s), keyID{ -1 } {}
};
size_t hashFunction(const string & key);
bool isActive(int currentPos) const;
int findPos(const string & keyTarget);
void reHash();
vector<hashEntry> hashVector;
int currentSize;
};
And a function header file (functions.h):
#pragma once
#include <iostream>>
#include <vector>
#include <string>
#include <fstream>
using std::string;
using std::cout;
using std::vector;
using std::endl;
using std::cin;
using std::ifstream;
using std::getline;
hashMap computeAdjacentWords(const vector<string> & words) //error at this line
{
hashMap hm(500);
//do stuff with object
return hm;
}
And the main file:
#include <iostream>>
#include <vector>
#include <string>
#include <fstream>
#include "hashMap.h"
using std::string;
using std::cout;
using std::vector;
using std::endl;
using std::cin;
using std::ifstream;
using std::getline;
int main()
{
vector<string> words;
string line;
ifstream dictionaryFile;
dictionaryFile.open("largedictionary.txt");
words = readinWords(dictionaryFile);
dictionaryFile.close();
hashMap hm = computeAdjacentWords(words);
return 0;
}
I created the hashMap class and I want to be able to return a hashMap object, but this is giving me an error of "Error C4430 missing type specifier - int assumed." What am I doing wrong?
I put the code in files and nicely asked the compiler to do its job. This is the first warning from the list:
$ cc main.cpp -c
In file included from main.cpp:5:
In file included from ./hashMap.h:6:
./functions.h:16:1: error: unknown type name 'hashMap'
hashMap computeAdjacentWords(const vector<string> & words) //error at this line
^
The compiler doesn't know what hashMap is. When it reaches the line with the error, the hashMap symbol was not yet declared or defined.
You shouldn't define functions in header files.
Rename functions.h to functions.cpp, add #include "functions.h" at the end of the list of includes.
Create a new file functions.h that contains only the declarations of the functions (the function header) and the types they use:
#ifndef __FUNCTIONS_H__
#define __FUNCTIONS_H__
#pragma once
//#include <iostream>
#include <vector>
#include <string>
//#include <fstream>
#include "hashMap.h"
using std::string;
using std::vector;
// Do you really need all these types here?
using std::cout;
using std::endl;
using std::cin;
using std::ifstream;
using std::getline;
hashMap computeAdjacentWords(const vector<string> & words);
#endif // __FUNCTIONS_H__
You are including functions.h from hashmap.h BEFORE the hashMap class is defined. As such, when the compiler reads functions.h, the hashMap class is not defined.

implementing map<mpz_t, double> in c++

For some reason, I need to have a map from arbitrary huge number to double and I tried to implement it with c++98 (and I have to) and Xcode but it doesn't work:
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <set>
#include "gurobi_c++.h"
#include <sstream>
#include "boost/tuple/tuple.hpp"
#include "boost/tuple/tuple_comparison.hpp"
#include "boost/tuple/tuple_io.hpp"
#include <cmath>
#include <gmp.h>
using namespace std;
using namespace ::boost::tuples;
using namespace ::boost;
int main()
{
map<mpz_t, double>J;
mpz_t a,b,c,n;
string tempstring;
int xrange=5,yrange=5,component=5;
mpz_set_str(n,"11", 10);
J[n]=-1;
return 0;
}
The error shown is: Array initializer must be an initializer list. Could someone help me with it? Thank you:)
Here's the detail error page:
I don't know the details of mpz_t. However, it appears to be an array.
You can get around the problem by defining a class to be used as the key in your map.
I am able to create an executable using the following code with g++ 4.8.2.
#include <map>
using namespace std;
typedef int (mpz_t)[2];
struct MyKey
{
// Add a proper implementation of a constructor
// with mpz_t.
MyKey(mpz_t in) {}
// Add a proper implementation of copy constructor.
MyKey(MyKey const& copy) {}
// Add a proper implementation of assignment operator.
MyKey& operator=(MyKey const& rhs)
{
return *this;
}
bool operator<(MyKey const& rhs) const
{
// Add a proper implementation.
return false;
}
mpz_t n;
};
int main()
{
map<MyKey, double> J;
mpz_t n;
J[n] = 1.0;
return 0;
}

use boost::boyer_moore with boost::gil

I want to search for a small image from a large one, my algorithm is:
search for the first line
if first line matches, then compare the rest
I want to use boost::algorithm::boyer_moore to do the line searching, it works fine with std::string:
#include <string>
using namespace std;
#include "boost/algorithm/searching/boyer_moore.hpp"
using namespace boost::algorithm;
int main() {
string s;
boyer_moore<string::iterator> bm(s.begin(), s.end()); // it compiles
}
the code compiles, but this one not:
#include "boost/mpl/vector.hpp"
using namespace boost;
#include "boost/gil/gil_all.hpp"
using namespace boost::gil;
#include "boost/algorithm/searching/boyer_moore.hpp"
using namespace boost::algorithm;
int main() {
typedef rgba8_image_t image_t;
typedef image_t::view_t view_t;
view_t vw;
boyer_moore<view_t::x_iterator> bm(vw.row_begin(0), vw.row_end(0)); // compile error
}
Both of them are iterators, what's wrong with the second one?
Thanks.
According to the docs the algorithm uses an auxiliary data structure called skip_table. By default (when the value_type of the iterator is not a char or unsigned char) this table uses a tr1::unordered_map, and this requires that gil::pixel be hash-able. So you have two options: you either change the default skip_table by specializing BM_traits for your iterator (this is sadly undocumented), or you make gil::pixel hash-able. For the latter you can create a std::size_t hash_value(pixel<ChannelValue,Layout> const& val) inside the namespace boost::gil. The following compiles with g++ 4.9.0 and Visual Studio 2013 (and does nothing):
#include <boost/functional/hash.hpp> //ADDED
#include <boost/mpl/vector.hpp>
#include <boost/gil/gil_all.hpp>
#include <boost/algorithm/searching/boyer_moore.hpp>
using namespace boost;
using namespace boost::gil;
using namespace boost::algorithm;
namespace boost {
namespace gil
{
template <typename ChannelValue, typename Layout>
std::size_t hash_value(pixel<ChannelValue, Layout> const& b)
{
std::size_t seed = 0;
for (int c = 0; c<num_channels<pixel<ChannelValue, Layout> >::value; ++c)
hash_combine(seed, b[c]);
return seed;
}
}
}
namespace std { //ADDED
template <typename ChannelValue, typename Layout>
struct hash<boost::gil::pixel<ChannelValue,Layout> > {
size_t operator ()(boost::gil::pixel<ChannelValue, Layout> const& value) const {
return hash_value(value);
}
};
}
int main() {
typedef rgba8_image_t image_t;
typedef image_t::view_t view_t;
view_t vw;
boyer_moore<view_t::x_iterator> bm(vw.row_begin(0), vw.row_end(0)); // compile error
}

possible bug in boost transformed adaptor

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;
}