I'm new to serialization, and I'm having trouble serializing std::vector objects with the Cereal library. Here's a sample that illustrates the problem:
class MyClass
{
int x, y, z;
class MyOtherClass
{
string name, description;
public:
template<class Archive>
void serialize(Archive & archive)
{
archive(name, description);
}
};
vector<MyOtherClass> Victor;
vector<int> ints;
public:
template<class Archive>
void serialize(Archive & archive)
{
archive(x, y, z, ints); // error C2338: cereal could not find any output serialization functions for the provided type and archive combination.
}
};
Attempting to serialize either the ints object or the Victor object results in error C2338: cereal could not find any output serialization functions for the provided type and archive combination.
Here's the code I use in the main function:
MyClass MyObject;
ofstream datafile(path, ios::binary);
{ cereal::BinaryOutputArchive oarchive(datafile); oarchive(MyObject); }
What am I doing wrong?
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;
#include <cereal/archives/json.hpp>
#include <cereal/types/vector.hpp>
// See details in http://uscilab.github.io/cereal/stl_support.html
class MyClass {
int x, y, z;
class MyOtherClass {
string name, description;
public:
template <class Archive>
void serialize( Archive &archive )
{
archive( CEREAL_NVP( name ), CEREAL_NVP( description ) );
}
};
vector<MyOtherClass> Vector;
vector<int> ints;
public:
template <class Archive>
void serialize( Archive &archive )
{
archive( CEREAL_NVP( x ), CEREAL_NVP( y ), CEREAL_NVP( z ), CEREAL_NVP( ints ) );
}
// Add one element to the private vector
void populateVector( const int value ) {
ints.push_back( value );
}
};
int main()
{
MyClass MyObject{};
MyObject.populateVector( 101 );
MyObject.populateVector( 202 );
MyObject.populateVector( 303 );
// For brevity I just print the serialization to the standard output instead of the binary file
cereal::JSONOutputArchive oarchive( cout );
oarchive( MyObject );
return 0;
}
This code should emit the following output:
{
"value0": {
"x": 0,
"y": 0,
"z": 0,
"ints": [
101,
202,
303
]
}
}
Related
I am trying to get the return type of a function that I bind in. In this instance I was expecting to see the return type of GetFactorialResult (int).
#include <iostream>
#include <boost/core/demangle.hpp>
#include <typeinfo>
namespace
{
const int testNumber = 10;
int GetFactorialResult(int number)
{
if (number > 1)
{
return number * GetFactorialResult(number - 1);
}
else
{
return 1;
}
}
template <typename Func, typename... Args>
void Submit(Func&& func, Args&&... args)
{
auto boundTask = std::bind(std::forward<Func>(func), std::forward<Args>(args)...);
using ResultType = typename std::result_of<decltype(boundTask)()>::type;
char const * name = typeid( ResultType ).name();
std::cout << boost::core::demangle( name ) << std::endl;
}
}
int main()
{
Submit([](int number)
{
GetFactorialResult(number);
}, number);
return 0;
}
Output
void
0
When I print the type of boundTask, I see what I expect:
std::_Bind<\main::{lambda(int)#1} (int)> (the backslash doesnt
exist, but couldnt figure out how to display it without it).
I assume I am getting void because of I'm doing decltype(boundTask)(), but if I remove the parenthesis, it fails to compile.
I only have access to c++11 features.
Hello I'm trying to use Boost.Test for my unit tests. However some of my functions return a collection of tuples, in a std::vector< std::tuple< TypeA, TypeB > >.
To work with BOOST_CHECK_EQUALS and BOOST_CHECK_EQUAL_COLLECTION, I specialized boost::test_tools::print_log_value to print nice tuples and vectors as the answer to this question explains. I also provide operator<< for tuples, so that my vector can use that while printing the whole vector. For cleanness this operator lies in the blank namespace.
However the compilation fails, as the implementation of boost::test_tools::print_log_value <std::vector<std::tuple<...>>> cannot find the operator<< for tuples.
Here is a minimal code which is, sorry, already quite verbose.
#define BOOST_TEST_MODULE my_test
#include <boost/test/included/unit_test.hpp>
#include <tuple>
#include <vector>
/////////////////
// std::vector //
/////////////////
// boost printing method
namespace boost {
namespace test_tools {
template< typename Type >
struct print_log_value< std::vector< Type > > {
void operator()( std::ostream& s, const std::vector< Type > &collection ) {
const int size = collection.size();
if( size == 0 ) {
s << "[]";
}
else {
s << "[ ";
for( int i =0; i <= size-2; ++i ) {
s << collection[i] << ", ";
}
s << collection[size-1] << " ]";
}
return s;
}
};
} //namespace test_tools
} //namespace boost
////////////////
// std::tuple //
////////////////
// recursive calls for printing
namespace tuple_print_aux{
template< int I, int J, typename... Types >
struct recursive_printer {
static void print( std::ostream& s, const std::tuple<Types...> &collection ) {
s << std::get< I >( collection ) << ", ";
recursive_printer< I+1, J-1, Types... >::print( s, collection );
}
};
template< int I, typename... Types >
struct recursive_printer< I, 1, Types... > {
static void print( std::ostream& s, const std::tuple<Types...> &collection ) {
s << std::get< I >( collection );
}
};
template< typename... Types >
void recursive_print( std::ostream& s, const std::tuple<Types...> &collection ) {
recursive_printer< 0, sizeof...(Types), Types... >::print( s, collection );
}
}
// output stream operator
template< typename... Types >
std::ostream& operator<<( std::ostream& s, const std::tuple<Types...> &collection ) {
s << "( ";
tuple_print_aux::recursive_print< Types... >( s, collection );
s << " )";
return s;
}
// boost printing method
namespace boost {
namespace test_tools {
template< typename... Types >
struct print_log_value< std::tuple< Types... > > {
void operator()( std::ostream& s, const std::tuple<Types...> &collection ) {
s << "( ";
tuple_print_aux::recursive_print< Types... >( s, collection );
s << " )";
}
};
} //namespace test_tools
} //namespace boost
BOOST_AUTO_TEST_CASE(my_test_case) {
//builds successfully
BOOST_CHECK_EQUAL( std::make_tuple(1,"a"), std::make_tuple(1,"a") );
//builds successfully
std::vector< int > v( 2, 3 ), w( 2, 7 );
BOOST_CHECK_EQUAL_COLLECTIONS( v.begin(), v.end(), w.begin(), w.end() );
//fails to build
std::vector< std::tuple<int,int> > a( 1, std::make_tuple(1,3) ), b( 1, std::make_tuple(2,2) );
BOOST_CHECK_EQUAL_COLLECTIONS( a.begin(), a.end(), b.begin(), b.end() );
};
Of course, putting the operator<< for std::tuples into the std namespace solve the problem, but this is a non-standard non-elegant solution.
So... how should I approach the problem. ?
Thank you for any help.
I believe you should declare
template< typename... Types >
std::ostream& operator<<( std::ostream& s, const std::tuple<Types...> &collection )
before the struct print_log_value< std::vector< Type > >. Also I think that the specialization of struct print_log_value for tuples is enough as the BOOST_CHECK_EQUAL_COLLECTIONS do not actually see the std::vector but an iterator on it.
Consider the following code:
#include <boost/iterator/iterator_facade.hpp>
#include <map>
// Class implements an stl compliant iterator to access the "sections" stored within a configuration.
template < typename _Iterator, typename _Reference >
class Section
: public boost::iterator_facade<
Section< _Iterator, _Reference >,
_Iterator,
boost::random_access_traversal_tag,
_Reference
>
{
private:
// Define the type of the base class:
typedef boost::iterator_facade<
Section< _Iterator, _Reference >,
_Iterator,
boost::random_access_traversal_tag,
_Reference
> base_type;
public:
// The following type definitions are common public typedefs:
typedef Section< _Iterator, _Reference > this_type;
typedef typename base_type::difference_type difference_type;
typedef typename base_type::reference reference;
typedef _Iterator iterator_type;
public:
explicit Section( const iterator_type it )
: m_it( it )
{ }
// Copy constructor required to construct a const_iterator from an iterator:
template < typename _U >
Section( const Section< _U, _Reference > it )
: m_it( it.m_it )
{ }
private:
// The following classes are friend of this class to ensure access onto the private member:
friend class boost::iterator_core_access;
template < typename _Iterator, typename _Reference > friend class Section;
void increment( ){ ++m_it; } // Advance by one position.
void decrement( ){ --m_it; } // Retreat by one position.
void advance( const difference_type& n ){ m_it += n }; // Advance by n positions.
bool equal( const this_type& rhs ) const{ return m_it == rhs.m_it; } // Compare for equality with rhs.
reference dereference( ) const { return m_it->second; } // Access the value referred to.
difference_type distance_to( const this_type& rhs ) const{ return rhs.m_it - m_it; } // Measure the distance to rhs.
private:
// Current "section" iterator:
iterator_type m_it;
};
struct Data
{
void f( ) const
{ }
};
typedef std::map< int, Data > map_type;
typedef Section< const map_type::const_iterator, const Data& > iterator_type;
map_type g_map;
iterator_type begin( )
{
return iterator_type( g_map.begin( ) );
}
void main( )
{
iterator_type i = begin( );
// i->f( ); // <--- error C2039: 'f' : is not a member of 'std::_Tree_const_iterator<_Mytree>'
( *i ).f( );
}
So the iterator facade shall return a reference to Data type. This works well when dereference operator is called but compile fails when operator->() is called. So I am a bit confused because operator->() tries to return a std::map::iterator. Any ideas ?
The iterator returns an iterator on dereference. To get the f part, you need to dereference twice.
It looks a lot like you misunderstood the meaning of the template arguments to iterator_facade. The second argument is not supposed to be any iterator type (this is what causes all your trouble). Instead you should use it to name your value_type.¹
From the way you specified the dereference operation (and Ref) and wanted to use it in main (i->f()) it looks like you just wanted to iterate the map's values. So, I'd rewrite the whole thing using more descriptive names as well, and here it is, working:
Live On Coliru
#include <boost/iterator/iterator_facade.hpp>
#include <map>
// Class implements an stl compliant iterator to access the "sections" stored within a configuration.
template <typename Map, typename Value = typename Map::mapped_type>
class MapValueIterator : public boost::iterator_facade<MapValueIterator<Map>, Value, boost::random_access_traversal_tag, Value const&> {
private:
// Define the type of the base class:
typedef Value const& Ref;
typedef boost::iterator_facade<MapValueIterator<Map>, Value, boost::random_access_traversal_tag, Ref> base_type;
public:
// The following type definitions are common public typedefs:
typedef MapValueIterator<Map> this_type;
typedef typename base_type::difference_type difference_type;
typedef typename base_type::reference reference;
typedef typename Map::const_iterator iterator_type;
public:
explicit MapValueIterator(const iterator_type it) : m_it(it) {}
// Copy constructor required to construct a const_iterator from an iterator:
template <typename U, typename V> MapValueIterator(const MapValueIterator<U,V> it) : m_it(it.m_it) {}
private:
// The following classes are friend of this class to ensure access onto the private member:
friend class boost::iterator_core_access;
template <typename U, typename V> friend class MapValueIterator;
void increment() { std::advance(m_it); } // Advance by one position.
void decrement() { std::advance(m_it, -1); } // Retreat by one position.
void advance(const difference_type &n) { std::advance(m_it, n); } // Advance by n positions.
bool equal(const this_type &rhs) const { return m_it == rhs.m_it; } // Compare for equality with rhs.
reference dereference() const { return m_it->second; } // Access the value referred to.
difference_type distance_to(const this_type &rhs) const { return rhs.m_it - m_it; } // Measure the distance to rhs.
private:
// Current iterator:
iterator_type m_it;
};
#include <iostream>
struct Data {
void f() const {
std::cout << __PRETTY_FUNCTION__ << "\n";
}
};
typedef std::map<int, Data> map_type;
template <typename Map>
MapValueIterator<Map> map_value_iterator(Map const& m) {
return MapValueIterator<Map>(m.begin());
}
int main() {
map_type g_map;
auto i = map_value_iterator(g_map);
i->f();
}
Which prints the output
void Data::f() const
as you'd expect.
Note that there are numerous places where I implemented the member functions using standard library facilities. Note as well, the iterator "mimics" random access, but it won't have the expected performance characteristics (increment is O(n)).
Final note: I'd recommend against having the implicit conversion constructor. I think you can do without it.
¹ The reference-type should typically be the same (but ref-qualified) except in rare cases where you actually "proxy" the values. This is an advanced topic and rarely should be used.
I am writing an application using the OpenCV libraries, the Boost libraries and a pieve of code that I have downloaded from this LINK. I have created a project under the same solution with Thunk32 and I have the following files:
MainProject.cpp
#include "stdafx.h"
int main( int argc, char** argv )
{
IplImage *img = cvLoadImage( "C:/Users/Nicolas/Documents/Visual Studio 2010/Projects/OpenCV_HelloWorld/Debug/gorilla.jpg" );
Window::WindowType1 *win = new Window::WindowType1("Something");
cvNamedWindow( "window", CV_WINDOW_AUTOSIZE );
cvShowImage( "window", img );
cvSetMouseCallback( "oonga", (CvMouseCallback)win->simpleCallbackThunk.getCallback(), NULL );
while( true )
{
int c = waitKey( 10 );
if( ( char )c == 27 )
{ break; }
}
return 0;
}
Window.h
class Window {
public:
Window();
virtual ~Window();
//virtual void mouseHandler( int event, int x, int y, int flags, void *param );
private:
void assignMouseHandler( CvMouseCallback mouseHandler );
class WindowWithCropMaxSquare;
class WindowWithCropSelection;
class WindowWithoutCrop;
public:
typedef WindowWithCropMaxSquare WindowType1;
typedef WindowWithCropSelection WindowType2;
typedef WindowWithoutCrop WindowType3;
protected:
};
class Window::WindowWithCropMaxSquare : public Window {
public:
indev::Thunk32<WindowType1, void _cdecl ( int, int, int, int, void* )> simpleCallbackThunk;
WindowWithCropMaxSquare( char* name );
~WindowWithCropMaxSquare();
void _cdecl mouseHandler( int event, int x, int y, int flags, void *param );
private:
protected:
};
and Window.cpp
#include "stdafx.h"
Window::Window()
{
}
Window::~Window()
{
}
void Window::assignMouseHandler( CvMouseCallback mouseHandler )
{
}
Window::WindowWithCropMaxSquare::WindowWithCropMaxSquare( char* name )
{
simpleCallbackThunk.initializeThunk(this, &Window::WindowWithCropMaxSquare::mouseHandler); // May throw std::exception
}
Window::WindowWithCropMaxSquare::~WindowWithCropMaxSquare()
{
}
void _cdecl Window::WindowWithCropMaxSquare::mouseHandler( int event, int x, int y, int flags, void *param )
{
printf("entered mousehandler");
}
Now, when I run this, If I don't move the mouse inside the window, it's ok and the callback has been successfully passed to the cvSetMouseCallback function. The cvSetMouseCallback function has three parameters 1. the name of the window, 2. the CvMouseCallback and the NULL character. The CvMouseCallback is defined as
typedef void (CV_CDECL *CvMouseCallback )(int event, int x, int y, int flags, void* param);
and the CV_CDECL is just a redefinition of the _cdecl calling convention.
#define CV_CDECL __cdecl
Now, my mouseHandler function is a class member function, which I assume conforms to the _thiscall calling convention.
My question is, why do I get the following error just when I put my mouse on the window, if it has managed to get into the method at least once? I guess there's a change the second moment my mouse moves within the windoow. Can anyone help me please?
Here's an image with what I am doing:
That thunk code uses the __stdcall convention, not __cdecl. In this case, since cvSetMouseCallback takes a void* which it passes through to the callback, I would recommend that you use a static callback function and use this data pointer to pass the this pointer. You may then put your logic in this static function or else just call an instance version of the callback using the pointer that was passed in.
class Window {
public:
void _cdecl staticMouseHandler( int event, int x, int y, int flags, void *param ) {
((MouseHandler*)param)->mouseHandler(event, x, y, flags, NULL);
}
// ...
}
// ...
cvSetMouseCallback( "oonga", &Window::staticMouseHandler, win );
I'm trying to implement a zip function. zip's parameters are each wrapped<Ti>, where Ti varies from parameter to parameter.
zip takes these wrapped<Ti>s and produces a wrapped<tuple<T1&,T2&,...TN&>>, or in other words a wrapped tuple of references to its parameters. The references should preserve const-ness.
Here's my first stab at zip with one parameter, which doesn't work in general:
#include <utility>
#include <tuple>
// implement forward_as_tuple as it is missing on my system
namespace ns
{
template<typename... Types>
std::tuple<Types&&...>
forward_as_tuple(Types&&... t)
{
return std::tuple<Types&&...>(std::forward<Types>(t)...);
}
}
template<typename T>
struct wrapped
{
wrapped(T &&x)
: m_x(std::forward<T>(x))
{}
T m_x;
};
template<typename T>
wrapped<std::tuple<T&&>>
zip(wrapped<T> &&x)
{
auto t = ns::forward_as_tuple(std::forward<T>(x.m_x));
return wrapped<std::tuple<T&&>>(t);
}
int main()
{
wrapped<int> w1(13);
wrapped<int> &ref_w1 = w1;
// OK
zip(ref_w1);
const wrapped<int> &cref_w1 = w1;
// XXX won't compile when passing a const reference
zip(cref_w1);
return 0;
}
Is there a way to implement the general, variadic case with a single version of zip?
Admittedly, I don't have a C++0x compiler that handles variadic templates, so I can't test it. But this might do the trick.
template<typename T>
struct wrapped
{
wrapped(T &&x)
: m_x(std::forward<T>(x))
{}
typedef T type;
T m_x;
};
template<typename... Types>
wrapped<std::tuple<Types&&...>> zip(wrapped<Types>&&... x)
{
return wrapped<std::tuple<Types&&...>>(std::tuple<Types&&...>(std::forward<Types>(x.m_x)...));
}
I'm not entirely sure if it is legal to call zip like this:
zip(wrapped<T1>(value1), wrapped<T2>(value2));
You may have to explicitly qualify the call:
zip<T1, T2>(wrapped<T1>(value1), wrapped<T2>(value2));
Here's the solution I arrived at:
#include <utility>
#include <tuple>
#include <cassert>
template<typename T>
struct wrapped
{
wrapped(T &&x)
: m_x(std::forward<T>(x))
{}
T m_x;
};
template<typename Tuple>
wrapped<Tuple> make_wrapped_tuple(Tuple &&x)
{
return wrapped<Tuple>(std::forward<Tuple>(x));
}
template<typename... WrappedTypes>
decltype(make_wrapped_tuple(std::forward_as_tuple(std::declval<WrappedTypes>().m_x...)))
zip(WrappedTypes&&... x)
{
return make_wrapped_tuple(std::forward_as_tuple(x.m_x...));
}
int main()
{
wrapped<int> w1(1);
wrapped<int> w2(2);
wrapped<int> w3(3);
wrapped<int> w4(4);
auto z1 = zip(w1,w2,w3,w4);
z1.m_x = std::make_tuple(11,22,33,44);
assert(w1.m_x == 11);
assert(w2.m_x == 22);
assert(w3.m_x == 33);
assert(w4.m_x == 44);
const wrapped<int> &cref_w1 = w1;
auto z2 = zip(cref_w1, w2, w3, w4);
// does not compile, as desired
// z2.m_x = std::make_tuple(111,222,333,444);
return 0;
}
Having zip take WrappedTypes... instead of wrapped<T>... isn't as satisfying a solution, but it works.
template<typename T>
struct wrapped
{
wrapped(T &&x)
: m_x(std::forward<T>(x))
{}
typedef T type;
T m_x;
};
template<typename... Types>
wrapped<std::tuple<T&&...>> zip(wrapped<Types>... &&x)
{
return G+