I have an input vector that can have any size between empty and 3 elements. I want the generated string to always be 3 floats separated by spaces, where a default value is used if there aren't enough elements in the vector. So far I've managed to output only the contents of the vector:
#include <iostream>
#include <iterator>
#include <vector>
#include "boost/spirit/include/karma.hpp"
namespace karma = boost::spirit::karma;
namespace phx = boost::phoenix;
typedef std::back_insert_iterator<std::string> BackInsertIt;
int main( int argc, char* argv[] )
{
std::vector<float> input;
input.push_back(1.0f);
input.push_back(2.0f);
struct TestGram
: karma::grammar<BackInsertIt, std::vector<float>(), karma::space_type>
{
TestGram() : TestGram::base_type(output)
{
using namespace karma;
floatRule = double_;
output = repeat(3)[ floatRule ];
}
karma::rule<BackInsertIt, std::vector<float>(), karma::space_type> output;
karma::rule<BackInsertIt, float(), karma::space_type> floatRule;
} testGram;
std::string output;
BackInsertIt sink(output);
karma::generate_delimited( sink, testGram, karma::space, input );
std::cout << "Generated: " << output << std::endl;
std::cout << "Press enter to exit" << std::endl;
std::cin.get();
return 0;
}
I've tried modifying the float rule to something like this: floatRule = double_ | lit(0.0f)
, but that only gave me compilation errors. The same for a lot of other similar stuff I tried.
I really have no idea how to get this working. Some help would be great :)
EDIT: Just to make it clear. If I have a vector containing 2 elements: 1.0 and 2.0, I want to generate a string that looks like this: "1.0 2.0 0.0"
(the last value should be the default value).
Big warning:
The code shown is flawed, either due to a bug, or due to abuse of karma attribute propagation (see the comment).
It invokes Undefined Behaviour (presumably) dereferencing the
end()
iterator on the input vector.This should workNote,
floatRule
should accept anoptional<float>
instead. See it Live on ColiruMinimal example:
Not pretty, but working: