Re: Using Tuple and bind in Spirit causes compiler error
Larry Evans <[email protected]> Sun, 25 Oct 2020 13:18:40 -0500
| Newsgroups | gmane.comp.parsers.spirit.general |
|---|---|
| Message-ID | <[email protected]> |
On 10/25/20 1:01 PM, Juan Dent wrote:
> Where do I add your code Larry?
>
> And do I only add this?
>
I'm sorry Juan, I should have just included the whole code.
Here it is:
//The code:
//The following code was copy&pasted from:
//
https://sourceforge.net/p/spirit/mailman/spirit-general/thread/PH0PR10MB4582B4450F828DD8F663A45E9B1A0%40PH0PR10MB4582.namprd10.prod.outlook.com/#msg37135371
//===========
// MVCE.cpp : This file contains the 'main' function. Program execution
begins and ends there.
//
#include <string>
#include <iostream>
#include <boost/optional/optional_io.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/phoenix/phoenix.hpp>
#include <boost/fusion/container/vector/vector.hpp>
#include <boost/tuple/tuple.hpp>
namespace fusion=boost::fusion;
using fusion::at_c;
using boost::optional;
enum tag_attribute
{ tag_tuple
, tag_vector
};
std::ostream&
operator<<
( std::ostream&sout
, tag_attribute tag
)
{
return sout<<((tag==tag_tuple)?"tag_tuple":"tag_vector");
}
template<tag_attribute TagAttribute=tag_vector>
struct which_attribute
{
using type=fusion::vector<optional<double>, optional<int> >;
};
template<>
struct which_attribute<tag_tuple>
{
using type=boost::tuple<optional<double>, optional<int> >;
};
#define TRY_USING_BOOST_TUPLE
// #defining this and TRY_USING_ACTION_PRINT creates compile error with
clang10.0.0:
/*
boost/spirit/home/qi/detail/assign_to.hpp:153:20: error: no matching
conversion for static_cast from 'const
boost::fusion::vector<boost::optional<double>, boost::optional<int> >' to
'boost::tuples::tuple<boost::optional<double>,
boost::optional<int>, boost::tuples::null_type, boost::tuples::null_type,
boost::tuples::null_type, boost::tuples::null_type,
boost::tuples::null_type, boost::tuples::null_type,
boost::tuples::null_type, boost::tuples::null_type>'
attr = static_cast<Attribute>(val);
^~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#ifdef TRY_USING_BOOST_TUPLE
tag_attribute constexpr which_tag=tag_tuple;
#include <boost/fusion/tuple.hpp>
#include <boost/fusion/adapted.hpp>
#define TRY_USING_ACTION_TRANSFORM_ATTRIBUTE//Try using the
transform_attribute in action.hpp
#ifdef TRY_USING_ACTION_TRANSFORM_ATTRIBUTE
namespace boost { namespace spirit { namespace traits
{
template<>
struct transform_attribute
< which_attribute<tag_tuple>::type
, which_attribute<tag_vector>::type
, qi::domain
>
{
typedef which_attribute<tag_vector>::type type;
typedef which_attribute<tag_tuple>::type orig_type;
static type pre(orig_type& ot)
{ std::cout<<"transform_attribute::pre\n";
return type{};
}
static void post(orig_type& ot, type& t)
{ std::cout<<"transform_attribute::post\n";
at_c<0>(ot)=at_c<0>(t);
at_c<1>(ot)=at_c<1>(t);
}
static void fail(orig_type&) {}
};
}}}
#endif//TRY_USING_ACTION_TRANSFORM_ATTRIBUTE
#else
tag_attribute constexpr which_tag=tag_vector;
#endif
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace phoenix = boost::phoenix;
using qi::int_;
using qi::double_;
using qi::_1;
using qi::_2;
using ascii::space;
#define TRY_USING_ACTION_PRINT
#ifdef TRY_USING_ACTION_PRINT
void print_pair(boost::optional<double> a, boost::optional<int> b)
{
if (a)
{
auto aa = *a;
std::cout << aa << std::endl;
}
if (b)
{
auto bb = *b;
std::cout << bb << std::endl;
}
}
#endif//TRY_USING_ACTION_PRINT
bool do_parse()
{
std::string s = "25 50.77 80";
std::cout<<"input="<<s<<"\n";
auto first = s.begin();
auto last = s.end();
which_attribute<which_tag>::type to;
bool r = qi::phrase_parse
( first
, last
, ( (double_ || int_)
#ifdef TRY_USING_ACTION_PRINT
[ phoenix::bind
( &print_pair
, _1
, _2
)
]
#endif
)
, space
, to
);
auto a = at_c<0>(to);
auto b = at_c<1>(to);
std::cout<<"attribute values: a="<<a<<": b="<<b<<"\n";
if (first == last)
{
std::cout<<"parse succeeded!\n";
}
else
{
std::cout<<"parse failed leaving:"<<std::string{first,last}<<"\n";
}
return r;
}
int main()
{
#if defined(BOOST_SPIRIT_ACTIONS_ALLOW_ATTR_COMPAT)
std::cout<<"BOOST_SPIRIT_ACTIONS_ALLOW_ATTR_COMPAT defined\n";
#else
std::cout<<"BOOST_SPIRIT_ACTIONS_ALLOW_ATTR_COMPAT undef\n";
#endif
#if defined(TRY_USING_ACTION_PRINT)
std::cout<<"TRY_USING_ACTION_PRINT defined\n";
#else
std::cout<<"TRY_USING_ACTION_PRINT undef\n";
#endif
#if defined(TRY_USING_BOOST_TUPLE)
std::cout<<"TRY_USING_BOOST_TUPLE defined\n";
#else
std::cout<<"TRY_USING_BOOST_TUPLE undef\n";
#endif
#if defined(TRY_USING_ACTION_TRANSFORM_ATTRIBUTE)
std::cout<<"TRY_USING_ACTION_TRANSFORM_ATTRIBUTE defined\n";
#else
std::cout<<"TRY_USING_ACTION_TRANSFORM_ATTRIBUTE undef\n";
#endif
std::cout<<"which_tag="<<which_tag<<"\n";
do_parse();
return 0;
}
//The output:
BOOST_SPIRIT_ACTIONS_ALLOW_ATTR_COMPAT undef
TRY_USING_ACTION_PRINT defined
TRY_USING_BOOST_TUPLE defined
TRY_USING_ACTION_TRANSFORM_ATTRIBUTE defined
which_tag=tag_tuple
input=25 50.77 80
transform_attribute::pre
25
50
transform_attribute::post
attribute values: a= 25: b= 50
parse failed leaving:.77 80