2013-11-27 4 views
7

की सीमाएं मैंने BOOST_FUSION_ADAPT_STRUCT मैक्रो के साथ खेलने की कोशिश की है और किसी भी मनमानी संरचना को मुद्रित करने के लिए फ़्यूज़न का उपयोग करने जैसी कुछ बेवकूफ चीजों की कोशिश की है।BOOST_FUSION_ADAPT_STRUCT

इस example code given in the documentation से शुरू, मैं अपने अनुकूलित संरचना पर कुछ संचालन करने में असमर्थ था जो एक संलयन अनुक्रम के साथ अनुमति है।

#include <boost/fusion/adapted.hpp> 
#include <boost/fusion/sequence/io/out.hpp> 
#include <boost/fusion/sequence/intrinsic.hpp> 
#include <boost/fusion/view.hpp> 
#include <iostream> 

namespace fuz = boost::fusion; 

namespace demo 
{ 
    struct employee 
    { 
     std::string name; 
     int age; 
    }; 
} 

// demo::employee is now a Fusion sequence 
BOOST_FUSION_ADAPT_STRUCT(
    demo::employee, 
    (std::string, name) 
    (int, age)) 

int main() 
{ 
    // tried to initialize an employee like a fusion sequence 
    // but it didnt work 
    // demo::employee e("bob", 42); 

    demo::employee e; 
    e.name = "bob"; 
    e.age = 42; 

    // Access struct members with fusion random access functions 
    // ok 
    std::cout << fuz::at_c<0>(e) << std::endl; 

    // tried to print the struct like any othe fusion sequence 
    // didnt work 
    // std::cout << e << std::endl; 

    // I made it work by using a fusion view 
    // is it the right way? 
    std::cout << fuz::as_nview<0, 1>(e) << std::endl; 
} 

यह मैं निम्न सवालों की ओर जाता है:

  • फ्यूजन magik यहाँ क्यों काम नहीं करता है?

  • एक दृश्य का उपयोग एक अनुकूलित संरचना मुद्रित करने का सही तरीका है?

  • फ़्यूज़न अनुक्रम के रूप में एक अनुकूलित संरचना का उपयोग कितना दूर किया जा सकता है?

उत्तर

8

boost::fusion प्रलेखन से:

आई/ओ ऑपरेटरों नाम स्थान बढ़ावा में अतिभारित रहे हैं :: संलयन

जिसका मतलब है कि आप इन operator<< का एक अंतर्निहित एकीकरण चाहते हैं, आपको अपने वर्तमान नेमस्पेस (::) में boost::fusion नेमस्पेस इंजेक्ट करने की आवश्यकता होगी, या स्पष्ट रूप से उनका उपयोग करें।

यह सब योग करने के लिए, जोड़ने:

using namespace boost::fusion; 

अपने मामले में काम करना चाहिए। या एक स्पष्ट उपयोग के लिए, आप होगा लिखने के लिए:

boost::fusion::operator<<(std::cout, e) << std::endl; 

--- संपादित करें ---

boost::fusion के कोड थोड़ा पढ़ने के बाद, यह लगता है कि आप की वजह से उलझन में हैं boost::fusion::operators::operator<< का चयन करें जो कि आपका तर्क वास्तविक boost::fusion::sequence है।

यही कारण है कि आप boost::fusion नाम स्थान इंजेक्षन की जरूरत नहीं है, और न ही स्पष्ट रूप से boost::fusion नाम स्थान में परिभाषित प्रकार के लिए boost::fusion::operator<< कहते हैं।

कुछ स्पष्टीकरण:

मैं कोएनिग के देखने (यह भी Argument Dependent Lookup रूप में जाना - ADL) की पूरी अवधारणा की व्याख्या नहीं होगा यहाँ के बाद से उस बिंदु नहीं है, लेकिन मूल रूप से, यह कहा गया है कि मामले में आप एक प्रयोग कर रहे हैं वेरिएबल जिसका नाम किसी नामस्थान के अंदर है, फिर फ़ंक्शन लुकअप उस पैरामीटर के नामस्थान तक फैला हुआ है।

इस विशेष मामले में, boost/fusion/sequence/io/out.hpp समेत boost::fusion::operator::operator<< परिभाषित करेगा जिसे boost::fusion नामस्थान में इंजेक्शन दिया जाएगा।

$ cat /usr/local/include/boost/fusion/sequence/io/out.hpp 
[...] 
namespace boost { namespace fusion 
{ 
    [...] 
    namespace operators 
    { 
     template <typename Sequence> 
     inline typename 
      boost::enable_if< 
       fusion::traits::is_sequence<Sequence> 
       , std::ostream& 
      >::type // this is just a SFINAE trick to ensure 
        // the function will only be selected for 
        // actual boost::fusion::sequence 
     operator<<(std::ostream& os, Sequence const& seq) 
     { 
      return fusion::out(os, seq); // this will print out the sequence 
     } 
    } 
    using operators::operator<<; // here the operator<< is injected 
           // in boost::fusion 
}} 

किoperator<< मापदंडों जिसका प्रकारboost::fusionनाम स्थान में हैं उचित अधिभार मिलेगा साथ का उपयोग कर कॉल इसका मतलब यह है।

इस नामस्थान में स्थित तर्कों का उपयोग करने वाले कॉल का उपयोग operator<< (यह आपके उदाहरण में मामला है) के उचित अधिभार को हल करने में विफल हो जाएगा।

आप boost::fusion नामस्थान में अपना प्रकार परिभाषित करके इसे देख सकते हैं।

namespace boost { namespace fusion { 
struct employee 
{ 
    std::string name; 
    int age; 
}; 
}} 

BOOST_FUSION_ADAPT_STRUCT(
    boost::fusion::employee, 
    (std::string, name) 
    (int, age)) 

[...] 
boost::fusion::employee e; 
std::cout << e << std::endl; // ADL will work here 

साइड नोट: यदि आप नाम देखने मुद्दों इस तरह डिबग करने के लिए चाहते हैं, आप gdb उपयोग करना चाहिए। इस तरह आप हमेशा जानते होंगे कि कौन सा अधिभार चुना गया था। इस मामले में:

$ cat fusion.cpp 
#include <iostream> 
#include <cstdlib> 

#include <boost/fusion/container/vector.hpp> 
#include <boost/fusion/sequence/io.hpp> 

int main(int, char**) 
{ 
    boost::fusion::vector<int, char> foo(42, '?'); 
    std::cout << foo << std::endl; 

    return EXIT_SUCCESS; 
} 

$ gdb -q ./fusion 
Reading symbols for shared libraries ... done 
(gdb) b 10 
Breakpoint 1 at 0x1000012f7: file fusion.cpp, line 10. 
(gdb) r 
Starting program: /Users/avallee/Projects/tmp/fusion 
Reading symbols for shared libraries ++............................. done 

Breakpoint 1, main (unnamed_arg=0x7fff5fbffb60, unnamed_arg=0x7fff5fbffb60) at fusion.cpp:10 
10 std::cout << foo << std::endl; 
(gdb) s 
boost::fusion::operators::operator<< <boost::fusion::vector<int, char, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> > ([email protected], [email protected]) at out.hpp:38 
38    return fusion::out(os, seq); 
4

धन्यवाद आपके महान विस्तृत स्पष्टीकरण के लिए बहुत सारे ऑरेलियन। मुझे Google समूह पर this post भी मिला है। जैसा कि आपकी व्याख्या के कारण काम करने के लिए सबसे आसान तरीका है, इसे डेमो नेमस्पेस में रखा गया है:

namespace demo{ 
    using boost::fusion::operators::operator<<; 
    ...