/ / बूस्ट कर्म: बढ़ावा देने पर डिफ़ॉल्ट पाठ उत्पन्न करें :: वैकल्पिक परेशान है - सी ++, बढ़ावा, बढ़ावा-भावना

बूस्ट कर्मा: बढ़ावा देने पर डिफ़ॉल्ट टेक्स्ट जेनरेट करें :: वैकल्पिक अनसेट है - सी ++, बूस्ट, बूस्ट-स्पिरिट

निम्नलिखित कार्यक्रम पर विचार करें:

using FooVariant = boost::variant<std::string, int>;
using FooOptional = boost::optional<FooVariant>;

template<typename OutputIt = boost::spirit::ostream_iterator>
struct FooGenerator
: boost::spirit::karma::grammar<OutputIt, FooOptional()>
{
FooGenerator()
: FooGenerator::base_type(start_)
{
namespace bsk = boost::spirit::karma;

foovar_ = bsk::auto_;
start_ = -foovar_;
}

boost::spirit::karma::rule<OutputIt, FooVariant()> foovar_;
boost::spirit::karma::rule<OutputIt, FooOptional()> start_;
};

int main()
{
FooVariant fv = "foo";
FooOptional fo = fv;
std::cout << boost::spirit::karma::format(FooGenerator<>(), fo) << std::endl;
}

जैसा कि उम्मीद थी यह प्रिंट होगा foo। इसी तरह अगर मैं इनिशियलाइज़ करूँ fo बस साथ:

FooOptional fo;

फिर कार्यक्रम कुछ भी नहीं प्रिंट करेगा, फिर से उम्मीद के मुताबिक। लेकिन कुछ नहीं छापने के बजाय, मैं छापना चाहूंगा - बजाय। इसलिए, मैंने अपना नियम बदल दिया start_ सेवा मेरे:

start_ = (foovar_ | "-");

लेकिन यह एक संकलन त्रुटि की ओर जाता है:

ALTERNATIVE_FUNCTION।hpp: 127: 34: त्रुटि: कोई सदस्य नामित नहीं है में "is_compatible" है "बढ़ावा :: भावना :: लक्षण :: compute_compatible_component, पूर्णांक>, बढ़ावा :: वैकल्पिक, int>>, बढ़ावा :: भावना :: कर्म :: डोमेन> " अगर (घटक_type :: is_compatible (आत्मा :: लक्षण :: जो (attr_)) ~~~~~~~~~~~~~~~~ ^

मैंने यह भी देखा कि अगर मैं हटा दूं FooVariant और बनाने के बजाय FooOptional = boost::optional<int> और अपने जनरेटर को अपडेट करें, अगर मैं इसे अनसेट वैकल्पिक कर देता हूं तो मैं एक दुर्घटना का उत्पादन कर सकता हूं उदाहरण के लिए:

int main()
{
FooOptional fo;
std::cout << boost::spirit::karma::format(FooGenerator<>(), fo) << std::endl;
}

जो मुझे विश्वास है कि मैं वैकल्पिक पीढ़ी का गलत तरीके से उपयोग कर रहा हूं। ऐसा करने का सही तरीका क्या है?

अद्यतन करें

थोड़ा और खोजबीन करने पर मुझे कुछ रोचक लगा। मेरा संशोधित कोड है:

using FooVariant = boost::variant<std::string, int>;
using FooOptional = boost::optional<int>;

template<typename OutputIt = boost::spirit::ostream_iterator>
struct FooGenerator
: boost::spirit::karma::grammar<OutputIt, FooOptional()>
{
FooGenerator()
: FooGenerator::base_type(start_)
{
namespace bsk = boost::spirit::karma;

foovar_ = bsk::int_;
start_ = (bsk::int_ | "-");
}

boost::spirit::karma::rule<OutputIt, int()> foovar_;
boost::spirit::karma::rule<OutputIt, FooOptional()> start_;
};

int main()
{
FooOptional fo;
std::cout << boost::spirit::karma::format(FooGenerator<>(), fo) << std::endl;
}

इसमें यह काम करता है कि यह प्रिंट होगा - या एक पूर्णांक मान यदि कोई असाइन किया गया है (जो कि चिपकाए गए कोड में नहीं है)। हालाँकि जब मैं अपना start_ इस पर शासन करें:

start_ = (foovar_ | "-");

मुझे एक खाली मूल्य पर एक दुर्घटना मिलती है।

उत्तर:

जवाब के लिए 2 № 1

मैं मानता हूं कि यह आपके लिए "आशा" के रूप में काम नहीं करता है। शायद एक व्यावहारिक सरलीकरण "नील" को एक भिन्न तत्व प्रकार के रूप में व्यक्त करना है:

struct Nil final {};

using FooVariant = boost::variant<Nil, std::string, int>;

अब एक डिफ़ॉल्ट-दूषित FooVariant शामिल है Nil। और नियम बस बन जाता है:

    start_  = string_ | bsk::int_ | "(unset)";

डेमो

वैंडबॉक्स पर लाइव

#include <boost/spirit/include/karma.hpp>

struct Nil final {};

using FooVariant = boost::variant<Nil, std::string, int>;

template<typename OutputIt = boost::spirit::ostream_iterator>
struct FooGenerator : boost::spirit::karma::grammar<OutputIt, FooVariant()>
{
FooGenerator()
: FooGenerator::base_type(start_)
{
namespace bsk = boost::spirit::karma;

string_ = """ << *("\" << bsk::char_("\"") | bsk::print | "\x" << bsk::right_align(2, "0")[bsk::hex]) << """;
start_  = string_ | bsk::int_ | "(unset)";
}

boost::spirit::karma::rule<OutputIt, std::string()> string_;
boost::spirit::karma::rule<OutputIt, FooVariant()> start_;
};

int main() {
for (auto fo : { FooVariant{}, {FooVariant{42}}, {FooVariant{"HellornWorld!"}} }) {
std::cout << boost::spirit::karma::format(FooGenerator<>(), fo) << std::endl;
}
}

प्रिंटों

(unset)
42
"Hellox0dx0aWorld!"