I need to deserialize a std::vector<boost::variant<..>> with decoration supplied by other objects.
One of the things the "decoration" enables is a empty entry in the vector. I have hit a brick wall in my real implementation. However, I have managed to shrink wrap it. Code that compiles :
#include <string>
#include <boost/spirit/include/karma.hpp>
#include <boost/variant.hpp>
#include <boost/cstdint.hpp>
namespace karma = boost::spirit::karma;
typedef boost::variant<boost::int32_t, boost::int64_t> custom_variant;
int main()
{
using karma::generate;
custom_variant v;
std::string temp;
std::back_insert_iterator<std::string> x(temp);
std::cout << v;
karma::generate(x, karma::auto_, v);
}
The offending changes, which attempt to implement a "undefined" type, along with the required concept.
#include <string>
#include <boost/spirit/include/karma.hpp>
#include <boost/variant.hpp>
#include <boost/cstdint.hpp>
namespace karma = boost::spirit::karma;
struct undefined{};
std::ostream & operator<<(std::ostream & out, undefined const & undefined)
{
return out;
}
typedef boost::variant<undefined,boost::int32_t, boost::int64_t> custom_variant;
int main()
{
using karma::generate;
custom_variant v;
std::string temp;
std::back_insert_iterator<std::string> x(temp);
std::cout << v;
karma::generate(x, karma::auto_, v);
}
If I comment out the karma::generate step, std::cout is a valid expression (Boost::variant OutputStreamable). Spirit requires that generators be given types which are OutputStreamable(spirit::karma OutputStreamable) and the variant above should be OutputStreamable since I have made the undefined typeOutputStreamable as a no-op.
What gives ? :(
I'm really beginning to question weather the C++ template mechanism is worth it when using libraries with > 2 levels of template indirection. Perhaps I should go back to straight-c.
Edit 1:
Ok, Clang gave me a sensible first error...
error: no type named 'properties' in 'boost::spirit::karma::no_auto_mapping_exists'
Now I got to figure out how to map undefined as a no-op to get a clean conversion. This spirit documentation entry (and this in specific) describes what I need to look into. Is there a generic undefined type provided by spirit or one defined in boost, that spirit already maps as a no-op ?
Edit 2:
std::vector<boost::optional<boost::variant<..>>> is beginning to look quite appealing since spirit provides type-deduction for them.
I'd suggest to use spirit::unused_type for that purpose as it already is 'known' to Spirit and it has an operator<<() predefined (but any other type will do) - not that you really need that operator for Karma in the first place.
In addition, you have to provide a specialization for create_generator (as you suspected):
namespace boost { namespace spirit { namespace traits
{
template <>
struct create_generator<spirit::unused_type>
{
typedef spirit::karma::eps_type type;
static type call()
{
return spirit::karma::eps;
}
};
}}}
which will map unused_type to karma::eps. This seems to be exactly what you need as eps eats the attribute without generating anything, while succeeding always. If you go this route you will not need to utilize optional<>.
Related
I have a boost mpl vector with different types and want to know if one specific type is in that vector. But that type contains a template parameter that is a boost placeholder (which I want to replace afterwards)
Code:
#define BOOST_MPL_LIMIT_VECTOR_SIZE 20
#define BOOST_MPL_LIMIT_MAP_SIZE 20
#include <boost/typeof/std/utility.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/contains.hpp>
namespace bmpl = boost::mpl;
template< class In, class Out = bmpl::_1 >
struct BSI{
typedef typename Out::FrameType FrameType;
};
int main(){
typedef BSI<float> foot;
typedef bmpl::vector< int, foot > vec;
typename bmpl::find_if< vec, bmpl::same_as<foot> >::type x;
}
Problem is: Boost seems to get confused by the placeholder and tries to apply my placeholder. Of course I can write an own placeholder and applier, but is this possible with boost itself?
It is important to note that Boost placeholders are not an "implementation" detail of Boost MPL but actually designed for use: http://www.boost.org/doc/libs/1_58_0/libs/mpl/doc/refmanual/apply.html
However the behaviour observed here seems to be expected: http://www.boost.org/doc/libs/1_57_0/libs/mpl/doc/tutorial/placeholders.html There they have an example:
mpl::multiplies<
mpl::plus<_1,_2>,
mpl::minus<_1,_2>
>
So Solution seems to be to wrap the class in question in a quoter (as mentioned in the comments) like:
template<class T>
struct Quote{
using type = T;
}
I'm still not sure if there is a prefered solution within the boost MPL like the protect or quote templates although I did not found appropriate examples for use of them.
I was attempting to follow the example of Finite State Filters in the Boost::iostreams documentation. However when I went to use the filter I got an error stating the ::imbue was not accessible because 'boost::iostreams::detail::finite_state_filter_impl' uses 'protected' to inherit from 'my_fsm'.
Frustrated I copied my code into the tests used to in the boost examples. The tests compile and pass. My conculsion is that I am probably mis-using the dual use filter defined by:
typedef io::finite_state_filter my_fsm_filter;
I feel that just pushing it onto a filtered_stream may not be proper, but I could not find a missing step. I am sure there must be a need to wrap the filter but I can find no example (though I am sure if I dug deep enough into the code used to test the boost code it has to be there somewhere).
here is a bit of example code:
#include <boost/mpl/vector.hpp>
#include <libs/iostreams/example/finite_state_filter.hpp>
namespace io = boost::iostreams;
struct my_fsm : io::finite_state_machine<my_fsm> {
BOOST_IOSTREAMS_FSM(my_fsm) // define skip and push.
typedef my_fsm self;
static const int beginline = 0;
static const int skipline = 1;
static const int dataline = 2;
typedef boost::mpl::vector <
row<beginline, is<'C'>, skipline, &self::skip>,
row<beginline, is_any, dataline, &self::push>,
row<skipline, is<'\n'>, beginline, &self::skip>,
row<skipline, is_any, skipline, &self::skip>,
row<dataline, is<'\n'>, beginline, &self::push>,
row<dataline, is_any, dataline, &self::push>
> transition_table;
};
typedef io::finite_state_filter<my_fsm> my_fsm_filter;
#include <iostream>
#include <string>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/stream.hpp>
namespace io = boost::iostreams;
int main() {
io::stream<io::file_sink> out(io::file_sink("outputfile.txt"));
io::filtering_istream in;
my_fsm_filter infsm;
in.push(my_fsm_filter());
in.push(io::file_source("inputdata.txt"));
while (in) {
std::string line;
if(std::getline(in, line)) {
//std::cout << line << std::endl;
out << line << std::endl;
}
}
return 0;
}
I personally feel that there is a bug in the sample header with respect to this imbue call.
However, you can work around it by changing the typedef to
struct my_fsm_filter : io::finite_state_filter<my_fsm> {
using io::finite_state_filter<my_fsm>::imbue;
};
This explicitly exposes the imbue method as public on the derived type. I haven't looked at the sample program that you reported to be working (because you didn't link to it). But it's possible they used a similar hack.
In my tests, a similar edit to finite_state_filte.hpp L278 to add
using base_type::imbue;
to class finite_state_filter has the same effect.
In C, if I use #include "someFile.h", the preprocessor does a textual import, meaning that the contents of someFile.h are "copy and pasted" onto the #include line. In C++, there is the using directive. Does this work in a similar way to the #include, ie: a textual import of the namespace?
using namespace std; // are the contents of std physically inserted on this line?
If this is not the case, then how is the using directive implemented`.
The using namespace X will simply tell the compiler "when looking to find a name, look in X as well as the current namespace". It does not "import" anything. There are a lot of different ways you could actually implement this in a compiler, but the effect is "all the symbols in X appear as if they are available in the current namespace".
Or put another way, it would appear as if the compiler adds X:: in front of symbols when searching for symbols (as well as searching for the name itself without namespace).
[It gets rather complicated, and I generally avoid it, if you have a symbol X::a and local value a, or you use using namespace Y as well, and there is a further symbol Y::a. I'm sure the C++ standard DOES say which is used, but it's VERY easy to confuse yourself and others by using such constructs.]
In general, I use explicit namespace qualifiers on "everything", so I rarely use using namespace ... at all in my own code.
No, it does not. It means that you can, from this line on, use classes and functions from std namespace without std:: prefix. It's not an alternative to #include. Sadly, #include is still here in C++.
Example:
#include <iostream>
int main() {
std::cout << "Hello "; // No `std::` would give compile error!
using namespace std;
cout << "world!\n"; // Now it's okay to use just `cout`.
return 0;
}
Nothing is "imported" into the file by a using directive. All it does is to provide shorter ways to write symbols that already exist in a namespace. For example, the following will generally not compile if it is the first two lines of a file:
#include <string>
static const string s("123");
The <string> header defines std::string, but string is not the same thing. You haven't defined string as a type, so this is an error.
The next code snippet (at the top of a different file) will compile, because when you write using namespace std, you are telling the compiler that string is an acceptable way to write std::string:
#include <string>
using namespace std;
static const string s("123");
But the following will not generally compile when it appears at the top of a file:
using namespace std;
static const string s("123");
and neither will this:
using namespace std;
static const std::string s("123");
That's because using namespace doesn't actually define any new symbols; it required some other code (such as the code found in the <string> header) to define those symbols.
By the way, many people will wisely tell you not to write using namespace std in any code. You can program very well in C++ without ever writing using namespace for any namespace. But that is the topic of another question that is answered at Why is "using namespace std" considered bad practice?
No, #include still works exactly the same in C++.
To understand using, you first need to understand namespaces. These are a way of avoiding the symbol conflicts which happen in large C projects, where it becomes hard to guarantee, for example, that two third-party libraries don't define functions with the same name. In principle everyone can choose a unique prefix, but I've encountered genuine problems with non-static C linker symbols in real projects (I'm looking at you, Oracle).
So, namespace allows you to group things, including whole libraries, including the standard library. It both avoids linker conflicts, and avoids ambiguity about which version of a function you're getting.
For example, let's create a geometry library:
// geo.hpp
struct vector;
struct matrix;
int transform(matrix const &m, vector &v); // v -> m . v
and use some STL headers too:
// vector
template <typename T, typename Alloc = std::allocator<T>> vector;
// algorithm
template <typename Input, typename Output, typename Unary>
void transform(Input, Input, Output, Unary);
But now, if we use all three headers in the same program, we have two types called vector, two functions called transform (ok, one function and a function template), and it's hard to be sure the compiler gets the right one each time. Further, it's hard to tell the compiler which we want if it can't guess.
So, we fix all our headers to put their symbols in namespaces:
// geo.hpp
namespace geo {
struct vector;
struct matrix;
int transform(matrix const &m, vector &v); // v -> m . v
}
and use some STL headers too:
// vector
namespace std {
template <typename T, typename Alloc = std::allocator<T>> vector;
}
// algorithm
namespace std {
template <typename Input, typename Output, typename Unary>
void transform(Input, Input, Output, Unary);
}
and our program can distinguish them easily:
#include "geo.hpp"
#include <algorithm>
#include <vector>
geo::vector origin = {0,0,0};
typedef std::vector<geo::vector> path;
void transform_path(geo::matrix const &m, path &p) {
std::transform(p.begin(), p.end(), p.begin(),
[&m](geo::vector &v) -> void { geo::transform(m,v); }
);
}
Now that you understand namespaces, you can also see that names can get pretty long. So, to save typing out the fully-qualified name everywhere, the using directive allows you to inject individual names, or a whole namespace, into the current scope.
For example, we could replace the lambda expression in transform_path like so:
#include <functional>
void transform_path(geo::matrix const &m, path &p) {
using std::transform; // one function
using namespace std::placeholders; // an entire (nested) namespace
transform(p.begin(), p.end(), p.begin(),
std::bind(geo::transform, m, _1));
// this ^ came from the
// placeholders namespace
// ^ note we don't have to qualify std::transform any more
}
and that only affects those symbols inside the scope of that function. If another function chooses to inject the geo::transform instead, we don't get the conflict back.
I am trying to compile the following code:
#include <iostream>
#include <iterator>
#include <vector>
#include <boost/assign/std/vector.hpp>
#include <boost/optional.hpp>
#include <boost/range/adaptor/indirected.hpp>
#include <boost/range/algorithm/copy.hpp>
int main( int argc, char ** argv )
{
using namespace boost::assign;
using boost::adaptors::indirected;
std::vector<boost::optional<unsigned> > values;
values += 1u,2u,3u;
boost::copy( values | indirected, std::ostream_iterator<unsigned>( std::cout, " " ) );
std::cout << std::endl;
}
However, I got some errors, e.g. that there is no type named element_type in boost::optional<unsigned>. The reference page page, however, says that the single precondition is the existence of the operator*() unary function. Is there a way to make it work?
This is definitely a bug in Boost, but whether that bug is in Boost.Optional or Boost.Iterator is up for debate (I would say the latter, personally).
However, the fix is trivial -- before including any Boost headers, do this:
#include <boost/optional/optional_fwd.hpp>
#include <boost/pointee.hpp>
namespace boost
{
template<typename P>
struct pointee<optional<P> >
{
typedef typename optional<P>::value_type type;
};
}
Then include other Boost headers as necessary.
Please submit a ticket on the Boost Trac, or at the least post a bug report on the Boost Users mailing list.
Look at the private optional.hpp defined in boost iostreams library here. You will see that it defines a typedef T element_type;
However the actual optional.hpp that you are using defined here does not define it. So that is why the compiler is complaining. I don't know why it was overlooked.
Try using the private optional.hpp from iostreams library to solve this issue. I hope this helps.
How do I map a key to a native data type like structure?
I wrote this snipped but I couldn't compile it. Do you have any ideas on how to fix it?
#include <map>
#include <iostream>
typedef struct _list
{
int a,b;
}list;
map<int,list> test_map;
int main(void)
{
cout <<"Testing"<< endl;
}
map resides in the std:: namespace. Two possible ways to fix this:
using namespace std;
// ...
map<int, list> test_map;
or
std::map<int, list> test_map;
I prefer the second method, but it's a purely personal choice.
On a related note, there is no real limitation on what you can put in a map, aside from the fact that they must be copyable/assignable, and that the key type must have a < operator (or you can also provide a comparer functor).
EDIT: Seems like <list> is included somewhere, either in <iostream> (unlikely) or <map> (strange but not impossible). A using namespace std will cause std::list to clash with your own struct. The solution: rename your struct, or remove the using namespace and put std:: where it's needed.
Added std where required.
Renamed list to mylist to avoid clash with std::list. Avoid typenames and variable names that clash with common usage.
Now compiles OK in VS2008.
#include <map>
#include <iostream>
typedef struct _list
{
int a,b;
} mylist;
std::map<int,mylist> test_map;
int main(void)
{
std::cout <<"Testing"<< std::endl;
return 0;
}
There's no issue with using your struct in the STL containers provided it's copyable cleanly (copy constructor), assignable (implements operator=) and comparable (implements operator<).
A number of problems here:
You're missing either a using::std or std::map, so the compiler doesn't know what map<int,list> means.
Assuming you have a using namespace std declaration, your typedef list might collide with the STL collection of the same name. Change the name.
Your typedef struct _tag {...} tag; construct is an archaic holdover from the 80's. It is not necesarry, and frankly rather silly. It gets you nothing.
Here's your code fixed:
#include <map>
#include <iostream>
struct MyList
{
int a,b;
};
std::map<int,MyList> test_map;
int main(void)
{
std::cout <<"Testing"<< std::endl;
return 0;
}
map<int, _list> test_map; or don't use list(much better) as a name of structure. (You probably also have
#include <list>
...
using namespace std;
somewhere in your code.
I would try to avoid using codepad at all.
I have done a couple of tests with your code and it seems that
it is adding an implicit (and unwanted) using namespace std --it does not require you to qualify map, cout or endl.
it is (probably) including more standard headers than you might want, including #include <list>.
That means that when the compiler looks at the code it is seeing two list, your version and the one in std. Because of the using directive, both are in scope in the line where you create the map and the compiler is not able to determine which to use.
Two simple things that you can do: change the name of your type for the simple test to something other than list (ouch! the tool forcing your naming choices!) or fully qualify the use:
#include <map>
struct list {
int a,b;
};
std::map< int, ::list > the_map;
// ...
Note that codepad is adding the include by itself and the using directive, so it will also compile:
struct list {
int a,b;
};
map<int,::list> the_map;
But that piece of code is wrong
You seem to be comming from C. Try this:
#include <map>
#include <iostream>
struct list
{
int a,b;
};
std::map<int,list> test_map;
int main(void)
{
std::cout <<"Testing"<< std::endl;
return 0;
}