How do I serialize std::chrono::minutes - c++11

How do I serialize std::chrono::minutes with cereal or in general?
I tried this
struct A {
std::chrono::minutes m;
template <class Archive>
void serialize(Archive& ar) {
ar(m);
}
};
int main()
{
A a;
std::ostringstream os;
cereal::JSONOutputArchive ar1(os);
ar1(cereal::make_nvp("A", a));
A result;
std::istringstream is(os.str());
cereal::JSONInputArchive ar2(is);
ar2(cereal::make_nvp("A", result));
if (a.m != result.m)
std::cout << "error\n";
}
but get an error in Visual Studio 2015
1> Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these).
1> Serialize functions generally have the following signature:
1>
1> template<class Archive>
1> void serialize(Archive & ar)
1> {
1> ar( member1, member2, member3 );
1> }
1>
1>
1> cereal.hpp(702): note: see reference to function template instantiation 'ArchiveType &cereal::InputArchive<ArchiveType,0>::processImpl<std::chrono::minutes,0>(const T &)' being compiled
1> with
1> [
1> ArchiveType=cereal::JSONInputArchive,
1> T=std::chrono::minutes
1> ]
Ideally I wan to serialize and deserialize in a portable way.
I think I solved the problem by including cereal/types/chrono.hpp
and changing to
#include <cereal/types/chrono.hpp>
class A {
std::chrono::minutes m;
friend class cereal::access;
template <class Archive>
void serialize(Archive& ar)
{
ar(m);
}
};

As you discovered, support for std::chrono::minute, which is really an std::chrono::duration, can be found by including cereal/types/chrono.hpp, which is included with cereal.

Related

ERROR C2993: when compile boost-1_72 with visual studio 2019 errors occur in vector.hpp file

I'm trying to compile a library which depends on boost-1_72 with visual studio 2019, but error occurs in vector.hpp file. the error is C2993 'J' is not a valid type for non-type template parameter 'J' at line 245, and another error is C4430 missing type specifier - int assumed.Note:C++ does not support default-int at line 252.
private:
template <std::size_t J>
using store_at = decltype(store_at_impl(static_cast<vector_data*>(nullptr)));
public:
template <typename J>
BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
typename store_at<J::value>::elem_type& at_impl(J)
{
return store_at<J::value>::elem;
}
template <typename J>
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
typename store_at<J::value>::elem_type const& at_impl(J) const
{
return store_at<J::value>::elem;
}
};
} // namespace boost::fusion::vector_detail

Need help linking code using Boost rtree for storing user-defined object in tree where object contains the indexable -a boost geometry box

I have a hard time following the C++ template and stl code of the open source boost library and hope someone can help with my code sample that tries to store a user defined object (Node) in a boost::geometry::index::rtree. The Node object contains the indexable and I am trying to define an indexable object that translates the Node to a box (retrieves the box member of Node).
I am using Visual Studio Express 2022 and Boost 1.79.0 under Windows 10.
This is the link error:
Microsoft (R) Build Engine version 17.0.0+c9eb9dd64 for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.
Automatic MOC and UIC for target BoostNodeTree
BoostNodeTree.cpp
E:\boost_1_79_0\boost/geometry/index/detail/translator.hpp(62,1): error C2662: 'const boost::geometry::index::node_indexable::result_type &boost::geometry::index::node_indexable::operator ()(const Node &)': cannot convert 'this' pointer from 'const boost::geometry::index::detail::translator<IndexableGetter,EqualTo>' to 'boost::geometry::index::node_indexable &' [C:\Users\Lawrence Travis\source\repos\BoostNodeTree\build\BoostNodeTree.vcxproj]
with
[
IndexableGetter=NodeTree::indexable_getter,
EqualTo=NodeTree::equal_to_getter
]
E:\boost_1_79_0\boost/geometry/index/detail/translator.hpp(62,33): message : Conversion loses qualifiers [C:\Users\Lawrence Travis\source\repos\BoostNodeTree\build\BoostNodeTree.vcxproj]
C:\Users\Lawrence Travis\source\repos\BoostNodeTree\NodeTree.h(22,36): message : see declaration of 'boost::geometry::index::node_indexable::operator ()' [C:\Users\Lawrence Travis\source\repos\BoostNodeTree\build\BoostNodeTree.vcxproj]
E:\boost_1_79_0\boost/geometry/index/rtree.hpp(1655): message : see reference to function template instantiation 'boost::geometry::model::box<point_t> boost::geometry::index::detail::translator<IndexableGetter,EqualTo>::operator ()<Node>(const Value &) const' being compiled [C:\Users\Lawrence Travis\source\repos\BoostNodeTree\build\BoostNodeTree.vcxproj]
with
[
IndexableGetter=NodeTree::indexable_getter,
EqualTo=NodeTree::equal_to_getter,
Value=Node
]
E:\boost_1_79_0\boost/geometry/index/rtree.hpp(1655): message : see reference to function template instantiation 'boost::geometry::model::box<point_t> boost::geometry::index::detail::translator<IndexableGetter,EqualTo>::operator ()<Node>(const Value &) const' being compiled [C:\Users\Lawrence Travis\source\repos\BoostNodeTree\build\BoostNodeTree.vcxproj]
with
[
IndexableGetter=NodeTree::indexable_getter,
EqualTo=NodeTree::equal_to_getter,
Value=Node
]
E:\boost_1_79_0\boost/geometry/index/rtree.hpp(1652): message : while compiling class template member function 'void boost::geometry::index::rtree<NodeTree::value,NodeTree::parameters,NodeTree::indexable_getter,NodeTree::equal_to_getter,boost::container::new_allocator<Value>>::raw_insert(const Node &)' [C:\Users\Lawrence Travis\source\repos\BoostNodeTree\build\BoostNodeTree.vcxproj]
with
[
Value=NodeTree::value
]
E:\boost_1_79_0\boost/geometry/index/rtree.hpp(832): message : see reference to function template instantiation 'void boost::geometry::index::rtree<NodeTree::value,NodeTree::parameters,NodeTree::indexable_getter,NodeTree::equal_to_getter,boost::container::new_allocator<Value>>::raw_insert(const Node &)' being compiled [C:\Users\Lawrence Travis\source\repos\BoostNodeTree\build\BoostNodeTree.vcxproj]
with
[
Value=NodeTree::value
]
C:\Users\Lawrence Travis\source\repos\BoostNodeTree\NodeTree.h(56): message : see reference to class template instantiation 'boost::geometry::index::rtree<NodeTree::value,NodeTree::parameters,NodeTree::indexable_getter,NodeTree::equal_to_getter,boost::container::new_allocator<Value>>' being compiled [C:\Users\Lawrence Travis\source\repos\BoostNodeTree\build\BoostNodeTree.vcxproj]
with
[
Value=NodeTree::value
]
Here is the code and thanks in advance for any help!
Node.h:
#pragma once
#include <Windows.h>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/box.hpp>
namespace bg = boost::geometry;
namespace bgi = boost::geometry::index;
typedef bg::model::point<int, 2, bg::cs::cartesian> point_t;
typedef bg::model::box<point_t> box_t;
using namespace std;
class Node
{
public:
typedef Node value_type;
typedef const value_type& const_reference;
typedef std::size_t size_type;
Node() {}
~Node() {}
bool equal_to(const Node& that) {
const box_t& box1 = this->getBox();
const box_t& box2 = that.getBox();
return box1.min_corner().get<0>() == box2.min_corner().get<0>() &&
box1.min_corner().get<1>() == box2.min_corner().get<1>() &&
box1.max_corner().get<0>() == box2.max_corner().get<0>() &&
box1.max_corner().get<1>() == box2.max_corner().get<1>();
}
void setBox(RECT rect) {
box = box_t(point_t(rect.left, rect.top), point_t(rect.right, rect.bottom));
}
const box_t& getBox() const {
return box;
}
protected:
box_t box;
};
NodeTree.h:
#pragma once
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/index/rtree.hpp>
#include "Node.h"
namespace bg = boost::geometry;
namespace bgi = boost::geometry::index;
namespace boost {
namespace geometry {
namespace index {
class node_indexable {
public:
typedef box_t result_type;
explicit node_indexable() {}
const result_type& operator()(const Node& node) {
return node.getBox();
}
};
template <typename NodeType>
class node_equal_to {
public:
typedef box_t result_type;
explicit node_equal_to() {}
bool equal_to(const NodeType& node1, const NodeType& node2) {
return node1.equal_to(node2);
}
};
} } }
class NodeTree {
public:
typedef Node value;
typedef bgi::linear<16> parameters;
typedef boost::geometry::index::node_indexable indexable_getter;
typedef boost::geometry::index::node_equal_to<Node> equal_to_getter;
bgi::rtree<value, parameters, indexable_getter, equal_to_getter> node_rtree;
NodeTree() {
parameters params;
indexable_getter ind;
equal_to_getter eq;
node_rtree = bgi::rtree<value, parameters, indexable_getter, equal_to_getter> (params, ind, eq);
}
void addNode(Node node) {
node_rtree.insert(node);
}
};
Class with main that triggers the link errors:
// BoostNodeTree.cpp :
//
#include <iostream>
#include "Node.h"
#include "NodeTree.h"
int main()
{
NodeTree nodeTree;
Node node;
RECT rect{ 10, 10, 100, 100 };
node.setBox(rect);
nodeTree.addNode(node);
}

Create a std::vector of type having private constructor

I have a class whose constructors are private. I need to create a std::vector of instances of this class. Now, I am providing my own allocator for this purpose and the class has the allocator as a friend. However on MSVS 2015 with C++11, I get the error as:
error C2664: 'const MyClass*std::_Wrap_alloc<MyClass::MyClassAllocator>::address(const MyClass&) const': cannot convert argument 1 from 'std::_Container_proxy' to 'MyClass&'
Here is my allocator:
struct MyClassAllocator: std::allocator<MyClass>
{
template <class U, class... Args>
void construct(U* ptr, Args&&... args)
{
::new(reinterpret_cast<void*>(ptr)) U(std::forward<Args>(args)...);
}
template <class U> struct rebind { typedef MyClassAllocator other; };
};
This allocator is taken from this SO answer.
Edit:
Here is a MVCE which produces the error in MSVC 2015 with update 3.
#include <vector>
class MyClass
{
friend struct MyClassAllocator;
public:
~MyClass() {}
private:
MyClass() {}
};
struct MyClassAllocator: std::allocator<MyClass>
{
template <class U, class... Args>
void construct(U* ptr, Args&&... args)
{
::new(reinterpret_cast<void*>(ptr)) U(std::forward<Args>(args)...);
}
template <class U> struct rebind { typedef MyClassAllocator other; };
};
int main()
{
std::vector<MyClass, MyClassAllocator> vector;
vector.emplace_back();
}
The error that is produced is:
tests.cpp
1>C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\vector(591): error C2664: 'const MyClass *std::_Wrap_alloc<MyClassAllocator>::address(const MyClass &) const': cannot convert argument 1 from 'std::_Container_proxy' to 'MyClass &'
1> C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\vector(586): note: while compiling class template member function 'void std::_Vector_alloc<std::_Vec_base_types<_Ty,_Alloc>>::_Free_proxy(void)'
1> with
1> [
1> _Ty=MyClass,
1> _Alloc=MyClassAllocator
1> ]
1> C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\vector(559): note: see reference to function template instantiation 'void std::_Vector_alloc<std::_Vec_base_types<_Ty,_Alloc>>::_Free_proxy(void)' being compiled
1> with
1> [
1> _Ty=MyClass,
1> _Alloc=MyClassAllocator
1> ]
1> C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\vector(680): note: see reference to class template instantiation 'std::_Vector_alloc<std::_Vec_base_types<_Ty,_Alloc>>' being compiled
1> with
1> [
1> _Ty=MyClass,
1> _Alloc=MyClassAllocator
1> ]
1> src\tests.cpp(157): note: see reference to class template instantiation 'std::vector<MyClass,MyClassAllocator>' being compiled
What am I doing wrong here?

Can't define std::function variable from the virtual method pointer in vs2013

In my project I am trying to define std::function variable from the virtual method pointer:
#include <functional>
class VirtualClass
{
public:
virtual void foo(int x) = 0;
};
class DerivedClass : public VirtualClass
{
public:
virtual void foo(int x) override
{
// I am foo from DerivedClass;
}
};
int main()
{
DerivedClass derivedClass;
std::function<void(VirtualClass&, int)> fooFunc = &VirtualClass::foo; //doesn't compile
fooFunc(derivedClass, 0);
return 0;
}
This code is compiling in visual studio 2017, but doesn't compile in visual studio 2013. Is it possible to fix a compilation error in vs 2013 without switching to pure pointers and keep using std::function?
update:
the error message is the following:
Error 1 error C2664: 'void std::_Func_class<_Ret,VirtualClass &,int>::_Set(std::_Func_base<_Ret,VirtualClass &,int> *)' : cannot convert argument 1 from '_Myimpl *' to 'std::_Func_base<_Ret,VirtualClass &,int> *' c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional 506 1 ConsoleApplication1

std::bind and boost::bind tricks

#include <functional>
#include <boost/bind.hpp>
class A
{
public:
A(){}
~A(){}
template<typename _Handler>
void call_handler(_Handler handler)
{
handler();
}
};
class B
{
public:
template<typename _Handler>
void call_handler(_Handler handler)
{
}
template<typename _Handler>
void run(_Handler handler)
{
m_a.call_handler(boost::bind(&B::call_handler<_Handler>, this, handler));
//only can use boost::bind here
}
A m_a;
};
class Test
{
public:
void handler()
{
}
};
int main()
{
B b;
Test t;
b.run(boost::bind(&Test::handler,&t));//only can use std::bind here
}
this is my little test code above.
I am confused that I only can use bind in the specific order...see note above
if I change std::bind to boost::bind ,then compiler failed,vice versa.
tested with:
gcc 4.9.2 for cygwin with option:
g++ -std=c++11 -fdiagnostics-color=always -fdiagnostics-show-location=every-line -I"/cygdrive/e/opensource libs/boost" main.cpp
msvc 12.0(visual studio 2013 with update4) with default option.
gcc diagnostic messages:
In file included from /cygdrive/e/opensource
libs/boost/boost/bind.hpp:22:0,
from main.cpp:3: /cygdrive/e/opensource libs/boost/boost/bind/bind.hpp: In instantiation of ‘void
boost::_bi::list2::operator()(boost::_bi::type, F&, A&,
int) [with F = boost::_mfi::mf1,
boost::_bi::list1 > > >; A =
boost::_bi::list0; A1 = boost::_bi::value; A2 =
boost::_bi::bind_t,
boost::_bi::list1 > >]’:
/cygdrive/e/opensource libs/boost/boost/bind/bind.hpp:893:50:
required from ‘boost::_bi::bind_t::result_type
boost::_bi::bind_t::operator()() [with R = void; F =
boost::_mfi::mf1,
boost::_bi::list1 > > >; L =
boost::_bi::list2, boost::_bi::bind_t,
boost::_bi::list1 > > >;
boost::_bi::bind_t::result_type = void]’ main.cpp:12:11:
required from ‘void A::call_handler(_Handler) [with _Handler =
boost::_bi::bind_t,
boost::_bi::list1 > > >,
boost::_bi::list2, boost::_bi::bind_t,
boost::_bi::list1 > > > >]’ main.cpp:27:3:
required from ‘void B::run(_Handler) [with _Handler =
boost::_bi::bind_t,
boost::_bi::list1 > >]’ main.cpp:44:38:
required from here /cygdrive/e/opensource
libs/boost/boost/bind/bind.hpp:313:34: error: invalid use of void
expression
unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_]);
^
msvc 12.0 diagnostic messages:
1>------ Build started: Project: scince_x32, Configuration: Debug
Win32 ------ 1> main.cpp 1>e:\opensource
libs\boost\boost\bind\bind.hpp(313): error C2664: 'void
boost::_mfi::mf1::operator ()(T *,A1) const' : cannot
convert argument 2 from 'void' to
'boost::_bi::bind_t,boost::_bi::list1>>'
1> with 1> [ 1>
_Handler=boost::_bi::bind_t,boost::_bi::list1>> 1> , T=B 1> , A1=boost::_bi::bind_t,boost::_bi::list1>> 1> ] 1> and 1> [ 1> T=Test * 1> ] 1> Expressions of type void cannot be
converted to other types 1> e:\opensource
libs\boost\boost\bind\bind.hpp(893) : see reference to function
template instantiation 'void
boost::_bi::list2,boost::_bi::bind_t,boost::_bi::list1>>>::operator
()(boost::_bi::type,F &,A &,int)' being
compiled 1> with 1> [ 1> T=B * 1> ,
F=boost::_mfi::mf1,boost::_bi::list1>>> 1> , A=boost::_bi::list0 1> ] 1> e:\opensource libs\boost\boost\bind\bind.hpp(893) : see reference to
function template instantiation 'void
boost::_bi::list2,boost::_bi::bind_t,boost::_bi::list1>>>::operator
()(boost::_bi::type,F &,A &,int)' being
compiled 1> with 1> [ 1> T=B * 1> ,
F=boost::_mfi::mf1,boost::_bi::list1>>> 1> , A=boost::_bi::list0 1> ] 1> e:\opensource libs\boost\boost\bind\bind.hpp(891) : while compiling
class template member function 'void
boost::_bi::bind_t,boost::_bi::list2,boost::_bi::bind_t,boost::_bi::list1>>>>::operator
()(void)' 1> with 1> [ 1>
_Handler=boost::_bi::bind_t,boost::_bi::list1>> 1> , T=B * 1> ] 1> e:\c++program\scince_x32\scince_x32\main.cpp(12) : see reference to
function template instantiation 'void
boost::_bi::bind_t,boost::_bi::list2,boost::_bi::bind_t,boost::_bi::list1>>>>::operator
()(void)' being compiled 1> with 1> [ 1>
_Handler=boost::_bi::bind_t,boost::_bi::list1>> 1> , T=B * 1> ] 1> e:\c++program\scince_x32\scince_x32\main.cpp(27) : see reference to
class template instantiation
'boost::_bi::bind_t,boost::_bi::list2,boost::_bi::bind_t,boost::_bi::list1>>>>'
being compiled 1> with 1> [ 1>
_Handler=boost::_bi::bind_t,boost::_bi::list1>> 1> , T=B * 1> ] 1> e:\c++program\scince_x32\scince_x32\main.cpp(44) : see reference to
function template instantiation 'void
B::run,boost::_bi::list1>>>(_Handler)'
being compiled 1> with 1> [ 1> T=Test *
1> ,
_Handler=boost::_bi::bind_t,boost::_bi::list1>> 1> ]
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
You're (indirectly) binding a bind-expression that binds as an argument another bind-expression.
In both Boost and standard library you need to protect the inner bind-expression so that the placeholders/bindings don't mix and conflict.
So it would begin with
m_a.call_handler(boost::bind(&B::call_handler<_Handler>, this, boost::protect(handler)));
Except, the protect(handler) wraps the type and it's no longer _Handler, so you need something else for &B::call_handler<???>. In my experience, the easiest by far, is to use a polymorphic function object:
struct handler_caller_f {
typedef void result_type;
template <typename H> void operator()(B* /*this_*/, H/* handler*/) const {
std::cout << __PRETTY_FUNCTION__ << "\n";
}
};
template <typename H> void run(H handler) {
m_a.call_handler(boost::bind(handler_caller_f(), this, boost::protect(handler)););
}
As you can see the function object replaces B::call_handler and removes the problem by deducing the type of handler again.
Here's a cleaned up version:
Using Boost
Live On Coliru
#include <boost/bind.hpp>
#include <boost/bind/protect.hpp>
#include <iostream>
struct A {
template <typename H> void call_handler(H handler) {
handler();
}
};
struct B {
struct handler_caller_f {
typedef void result_type;
template <typename H> void operator()(B* this_, H handler) const {
handler();
}
};
template <typename H> void run(H handler) {
m_a.call_handler(boost::bind(handler_caller_f(), this, boost::protect(handler)));
}
A m_a;
};
struct Test {
void handler() { std::cout << __PRETTY_FUNCTION__ << "\n"; }
};
int main() {
Test t;
B b;
b.run(boost::bind(&Test::handler, &t));
}
Prints
void Test::handler()
Using std::bind
Standard library doesn't have protect, but it's easy to add:
Live On Coliru
#include <functional>
#include <iostream>
namespace std_ex { // http://stackoverflow.com/questions/18519087/why-is-there-no-stdprotect
template <typename T> struct protect_wrapper : T {
protect_wrapper(const T &t) : T(t) {}
protect_wrapper(T &&t) : T(std::move(t)) {}
};
template <typename T>
typename std::enable_if<!std::is_bind_expression<typename std::decay<T>::type>::value, T && >::type protect(T &&t) {
return std::forward<T>(t);
}
template <typename T>
typename std::enable_if<std::is_bind_expression<typename std::decay<T>::type>::value,
protect_wrapper<typename std::decay<T>::type> >::type
protect(T &&t) {
return protect_wrapper<typename std::decay<T>::type>(std::forward<T>(t));
}
}
struct A {
template <typename H> void call_handler(H handler) { handler(); }
};
struct B {
struct handler_caller_f {
typedef void result_type;
template <typename H> void operator()(B *this_, H handler) const { handler(); }
};
template <typename H> void run(H handler) {
m_a.call_handler(std::bind(handler_caller_f(), this, std_ex::protect(handler)));
}
A m_a;
};
struct Test {
void handler() { std::cout << __PRETTY_FUNCTION__ << "\n"; }
};
int main() {
Test t;
B b;
b.run(std::bind(&Test::handler, &t));
}

Resources