Boost Polygon Serialization - boost

I am using boost geometry in my project, and I need to serialize polygons. I have been using boost serialization without problems for many boost data types, but boost geometry seems that currently does not support serialization, as I cannot find any header inside serialization folder.
Is there any well known method to achieve this?
Thanks.
EDIT: Binary Serialization Example in: Boost Polygon Serialization: Ring

I agree, it is weird that Boost.Geometry does not support Boost.Serialization. Probably it is hard to support all possible combinations of template parameters, or maybe they did not bother as WKT is already provided.
At least in the case of "default" container types it is trivial to add such functionality. The code below implements it and is fully functional.
Below I assume you use a custom class (QPoint from Qt) as your point class. Code for other point types will be almost identical to mine.
First, you add a serialization for the Point class:
#include <QPoint>
#include <boost/geometry/geometry.hpp>
#include <boost/geometry/geometries/register/point.hpp>
BOOST_GEOMETRY_REGISTER_POINT_2D_GET_SET(QPoint, int, cs::cartesian, x, y, setX, setY);
typedef QPoint MyPoint;
namespace boost {
namespace serialization {
template<class Archive>
void serialize(Archive & ar, MyPoint& pt, const unsigned int version) {
ar & boost::serialization::make_nvp("x", pt.rx() );
ar & boost::serialization::make_nvp("y", pt.ry() );
}
} //namespace serialization
} //namespace boost
Next you add serialization for Ring and Polygon. Here I use the fact that Ring and Polygon are essentially std::vector(s) of points and rings respectively and the serialization for std::vector is built-in in Boost.Serialization.
#include <boost/serialization/vector.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/geometries/ring.hpp>
//change template flags as you are pleased but ring and polygon has to be
//in correspondence w.r.t. to "closed" and "clockwise" policies
typedef boost::geometry::model::ring<MyPoint, false, true> MyRing;
typedef boost::geometry::model::polygon<MyPoint, false, true> MyPolygon;
namespace boost {
namespace serialization {
//Default ring<MyPoint> simply inherits from std::vector<MyPoint>,
//its serialization is trivial and no implementation is needed.
//Default polygon<MyPoint> gives direct access to outer ring and the container of inner rings
template<class Archive>
void serialize(Archive & ar, MyPolygon& poly, const unsigned int version) {
ar & boost::serialization::make_nvp("outer", poly.outer());
ar & boost::serialization::make_nvp("inners", poly.inners());
}
} //namespace serialization
} //namespace boost
That's it, you are done, now you can use MyPolygon with Boost.Serialize as any other class:
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
void foo_out(std::ostream & oss, const MyPolygon & poly)
{
boost::archive::xml_oarchive oa(oss);
oa & BOOST_SERIALIZATION_NVP(poly);
}
void foo_in(std::istream & iss, MyPolygon & poly)
{
boost::archive::xml_iarchive ia(iss);
ia & BOOST_SERIALIZATION_NVP(poly);
}
Enjoy!

Boost.Geometry does not support Boost.Serialization. You can read and write WKT (well-known text), this is a standardized ASCII format used by many databases too. See for example:
http://en.wikipedia.org/wiki/Well-known_text
There is also WKB (well-known binary) but that is not yet 100% supported. However, for polygons it is supported.

Related

std::vector of type deduced from initializers before C++17 ... any workaround for C++11?

I learned that from C++17, with the deduction guides, template arguments of std::vector can be deduced e.g. from the initialization:
std::vector vec = { function_that_calculate_and_return_a_specifically_templated_type() }
However I do not have the luxury of C++17 in the machine where I want to compile and run the code now.
Is there any possible workaround for C++11? If more solutions exist, the best would be the one that keep the readability of the code.
At the moment the only idea that I have is to track the various cases along the code (luckily they should not be too many) and make some explicit typedef/using.
Any suggestion is very welcome
The usual way to use type deduction for class template when CTAD is not available is providing a make_* function template, e.g. for your case (trailing return type is necessary for C++11):
#include <vector>
#include <type_traits>
#include <tuple>
template <class ...Args>
auto make_vec(Args&&... args) ->
std::vector<typename std::decay<typename std::tuple_element<0, std::tuple<Args...>>::type>::type>
{
using First = typename std::decay<typename std::tuple_element<0, std::tuple<Args...>>::type>::type;
return std::vector<First>{std::forward<Args>(args)...};
}
You can invoke the above with
const auto v = make_vec(1, 2, 3);
which gets at least kind of close to CTAD in the sense that you don't have to explicitly specify the vector instantiation.
While the answer by lubgr is a correct way, the following template is simpler and seems to work as well:
#include <vector>
#include <string>
template <typename T>
std::vector<T> make_vec(const std::initializer_list<T> &list)
{
return std::vector<T>(list);
}
int main()
{
auto v = make_vec({1,2,3});
auto v2 = make_vec({std::string("s")});
std::string s("t");
auto v3 = make_vec({s});
return v.size() + v2.size() + v3.size();
}
One advantage of using the initializer_list template directly are more clear error messages if you pass mixed types like in make_vec({1,2,"x"});, because the construction of the invalid initializer list now happens in non-templated code.

C++11, Is it possible to force an instance to be extern but also a constant expression of a non-type template parameter?

Using C++11, g++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-18).
Lets pretend I have a templated function (pardon my terminology if it isn't quite right).
I want to perform a "general" algorithm based on what was supposed to be compile-time instances of "field". Where the only things that really changed are these constants which I moved into trait classes (only added one here but imagine there are more). Originally I was declaring it as
constexpr field FIELD1{1};
However in C++11, non-type template params need to have external linkage (unlike C++14 which can have internal and external linkage?). So because not's in the same translation unit I needed to use extern in order to give it external linkage (sorry if I butchered that explanation also). But by defining it extern I can't define it using constexpr and it seems that losing that constexpr constructor this field is no longer a valid constant expression to qualify as a non-type template param.
Any suggestions if there is some way I can get around this? Open to a new method of doing things. Below is a simplified (incomplete, and non-compiling version to get the gist of the organization).
So the error I am seeing is along the lines of
error: the value of ‘FIELD1’ is not usable in a constant expression
note: ‘FIELD1’ was not declared ‘constexpr’
extern const field FIELD1;
Not quite sure what could be a best alternative.
I can get rid of the second error by removing the constexpr from the constructor. But then I don't know how to approach the constant expression issue.
field.H
struct field
{
int thingone;
constexpr field(int i):thingone(i){}
};
extern const field FIELD1;
field.C
#include "field.H"
const field FIELD1{0};
field_traits.H
#include "field.H"
template< const field& T >
class fieldTraits;
template< >
class fieldTraits<FIELD1>
{
public:
// Let's say I have common field names
// with different constants that I want to plug
// into the "function_name" algorithm
static constexpr size_t field_val = 1;
};
function.H
#include "field.H"
template< const field& T, typename TT = fieldTraits<T> >
void function_name()
{
// Let's pretend I'm doing something useful with that data
std::cout << T.thingone << std::endl;
std::cout << TT::field_val << std::endl;
}
So because not's in the same translation unit I needed to use extern in order to give it external linkage (sorry if I butchered that explanation also). But by defining it extern I can't define it using constexpr [...]
Per my comment, you can. It wouldn't work for you, but it's a step that helps in coming up with something that would work:
extern constexpr int i = 10;
This is perfectly valid, gives i external linkage, and makes i usable in constant expressions.
But it doesn't allow multiple definitions, so it can't work in a header file which is included in multiple translation units.
Ordinarily, the way around that is with inline:
extern inline constexpr int i = 10;
But variables cannot be declared inline in C++11.
Except... when they don't need to be declared inline because the effect has already been achieved implicitly:
struct S {
static constexpr int i = 10;
};
Now, S::i has external linkage and is usable in constant expressions!
You may not even need to define your own class for this, depending on the constant's type: consider std::integral_constant. You can write
using i = std::integral_constant<int, 10>;
and now i::value will do exactly what you want.

When initializing an atomic class member it requires a 'deleted' function, but adding it would make it no longer trivially copyable

When initializing an atomic class member it requires a 'deleted' function, but adding it would make it no longer trivially copyable which is a requirement for an object/struct to be atomic. Am I just not understanding how to do this correctly, or is this a problem in the c++ standard?
Take the example below:
#include <atomic>
#include <cstdint>
template<typename T>
struct A
{
T * data;
std::atomic<uintptr_t> next;
};
template<typename T>
class B
{
std::atomic<A<T>> myA;
public:
B ( A<T> & a ) noexcept
{
myA.store(a, std::memory_order_relaxed );
}
};
int main ()
{
A<int> a;
B<int> b(a);
return 0;
}
Trying to compile this with g++ gives error: use of deleted function 'A<int>::A(const A<int>&)' myA.store(a, std::memory_order_relaxed);. My understanding of this error is that the atomic::store method is looking for that constructor in my struct A but not finding it.
Now here is what happens when I add that constructor:
#include <atomic>
#include <cstdint>
template<typename T>
struct A
{
T * data;
std::atomic<uintptr_t> next;
A(const A<T>& obj) { }
A( ) { }
};
template<typename T>
class B
{
std::atomic<A<T>> myA;
public:
B ( A<T> & a ) noexcept
{
myA.store(a, std::memory_order_relaxed );
}
};
int main ()
{
A<int> a;
B<int> b(a);
return 0;
}
I no longer receive the above compiler error but a new one coming from the requirements of the atomic class required from 'class B<int>' .... error: static assertion failed: std::atomic requires a trivially copyable type ... In other words by adding the used-defined constructors I have made my struct A a non-trivially copyable object which cannot be initialized in class B. However, without the user-defined constructors I cannot use the store method in myA.store(a, std::memory_order_relaxed).
This seems like a flaw in the design of the std::atomic class. Now maybe I am just doing something wrong because I don't have a lot of experience using C++11 and up (I'm old school). Since 11 there have been a lot of changes and the requirements seem to be a lot stricter. I'm hoping someone can tell me how to achieve what I want to achieve.
Also I cannot change std::atomic<A<T>> myA; to std::atomic<A<T>> * myA; (changed to pointer) or std::atomic<A<T>*> myA;. I realize this will compile but it will destroy the fundamental design of a class I am trying to build.
The problem here resides in the fact that std::atomic requires a trivially copiable type. This because trivially copyable types are the only sure types in C++ which can be directly copied by copying their memory contents directly (eg. through std::memcpy). Also non-formerly trivially copyable types could be safe to raw copy but no assumption can be made on this.
This is indeed important for std::atomic since copy on temporary values is made through std::memcpy, see some implementation details for Clang for example.
Now at the same time std::atomic is not copy constructible, and this is for reasonable reasons, check this answer for example, so it's implicitly not trivially copyable (nor any type which contains them).
If, absurdly, you would allow a std::atomic to contain another std::atomic, and the implementation of std::atomic contains a lock, how would you manage copying it atomically? How should it work?

Runtime iteration over tuple types without construction

I have a std::tuple (or a boost fusion tuple) whose elements cannot be trivially constructed (for example references) and I want to iterate over the types but not the values of the elements.
In this example I have a (general) tuple type and I want to generate a vector with (runtime) type information. The example below works if all the types in the sequence are trivially default constructed but not in general.
In summary, I want a function that transform: std::tuple<...> -> std::vector<std::type_index>
#include <boost/fusion/adapted/std_tuple.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <typeindex>
#include<vector>
using tuple_type = std::tuple<std::string&, int>;
int main(){
std::vector<std::type_index> types;
boost::fusion::for_each(
tuple_type{}, // fails because of std::string&
[&types](auto& e){types.push_back(typeid(e));}
);
}
The problem is that I have to generate runtime information from non runtime information and I can't figure out how to mix the fusion functions (http://www.boost.org/doc/libs/1_59_0/libs/fusion/doc/html/fusion/algorithm/iteration/functions.html) and the metafunctions (http://www.boost.org/doc/libs/1_41_0/libs/fusion/doc/html/fusion/algorithm/iteration/metafunctions.html).
I tried with boost::fusion::accumulate and boost::fold but the situation is always the same, at some point I have to generate a runtime element in order to apply the algorithm.
EDIT: I solved the original problem (std::tuple<...> -> std::vector<std::type_index>). I can't imagine another context at the moment but maybe the fundamental question still stands.
I did it by using a trick involving expanding a parameter pack over the typeid function in the constructor of std::vector (or std::array).
template<class... Args>
std::array<std::type_index, sizeof...(Args)> const& types_info<std::tuple<Args...>>::value{typeid(Args)...};
The complete code is this (note that I also decided to use std::array).
#include <typeindex>
#include<array>
#include<iostream>
template<class T>
struct types_info;
template<class... Args>
struct types_info<std::tuple<Args...>>{
static std::array<std::type_index, sizeof...(Args)> const& value;//{typeid(Args)...};
};
template<class... Args>
std::array<std::type_index, sizeof...(Args)> const& types_info<std::tuple<Args...>>::value{typeid(Args)...};
// vvv works only in C++1z
template<template<typename...> typename T, class... Args> // non tuples types as well
struct types_info<T<Args...>> : types_info<std::tuple<Args...>>{};
using tuple_type = std::tuple<std::string&, int>;
int main(){
std::vector<std::type_index> types;
std::cout << types_info<tuple_type>::value.size() << std::endl;
std::cout << types_info<std::map<int, std::string>>::value.size() << std::endl;
}

Is there a way to use Boost serialization on stl functional

I have an stl functional std::function<int(int,int)> fcn_ as a member field of a class. Is there a way to serialize it using boost serialization? If I do the following
template<class Archive>
void serialize(Archive &ar, const unsigned int version) {
ar & fcn_;
}
I got the error
/opt/local/include/boost/serialization/access.hpp:118:9: error: 'class std::function<int(int, int)>' has no member named 'serialize'
Is there a header file (say something like<boost/serialization/vector.hpp>) I can include that implements serialize for std::function? Or is there an easy way to implement one myself?
Thanks!
I haven't had a look at how Boost serialization works, but here is a possible approach.
template<typename T>
std::ostream& serialize(std::ostream& out, const std::function<T>& fn)
{
using decay_t = typename std::decay<T>::type;
if(fn.target_type() != typeid(decay_t)) throw std::runtime_error(std::string(typeid(decay_t).name()) + " != " + fn.target_type().name());
const auto ptr = fn.template target<decay_t>();
out << reinterpret_cast<void*>(*ptr);
return out;
}
template<typename T>
std::istream& deserialize(std::istream& in, std::function<T>& fn)
{
using decay_t = typename std::decay<T>::type;
void* ptr = nullptr;
in >> ptr;
fn = reinterpret_cast<decay_t>(ptr);
return in;
}
Please note that this will not work if you are storing lambdas or function objects in your std::functions (as per http://en.cppreference.com/w/cpp/utility/functional/function/target).
A running example can be found coliru.
You could require my_serializable_function<int(int,int)> which knows how to self-describe and reconstruct from such a descriptor.
In other words: you write the code yourself.
Alternatively, you might look at a scripting engine, which already contains stuff like this (Boost Python, several Lua bindings, v8 engine etc.). Though each comes with their own set of trade-offs and might be overkill.
Thanks to Tom and sehe's response. After some research, I realized what I had in mind is not really possible in C++ --- it is generally not possible to serialize an std::function object. By "serialize", I mean being able to transfer (read/write) the object as a byte stream from one program to another program, or to the same program but a different invocation on the same or a different machine. The links below has more discussion about this topic:
Serializing function objects
Can std::function be serialized?

Resources