2012-05-30 13 views
10

मेरे पास मेरे नेमस्पेस ns में एक फ़ंक्शन है जो मुझे एसटीएल कंटेनर प्रिंट करने में मदद करता है। उदाहरण के लिए:बूस्ट :: एक एसडीडी कंटेनर प्रारूप और कस्टम प्रिंटिंग

template <typename T> 
std::ostream& operator<<(std::ostream& stream, const std::set<T>& set) 
{ 
    stream << "{"; 
    bool first = true; 
    for (const T& item : set) 
    { 
     if (!first) 
      stream << ", "; 
     else 
      first = false; 
     stream << item; 
    } 
    stream << "}"; 
    return stream; 
} 

यह operator << के साथ सीधे मुद्रण के लिए महान काम करता है:

std::set<std::string> x = { "1", "2", "3", "4" }; 
std::cout << x << std::endl; 
हालांकि

, का उपयोग कर boost::format असंभव है:

std::set<std::string> x = { "1", "2", "3", "4" }; 
boost::format("%1%") % x; 

समस्या काफी स्पष्ट है: बूस्ट पता नहीं है कि मैं अपने कस्टम operator << का उपयोग उन प्रकारों को प्रिंट करने के लिए करना चाहूंगा जिनके पास मेरे नेमस्पेस से कुछ लेना देना नहीं है। usingboost/format/feed_args.hpp में घोषणा जोड़ने के बाहर, बनाने के लिए कोई आसान तरीका है operator <<?

+1

मैं दृढ़ता से sugge आप [इस सवाल] (http://stackoverflow.com/q/4850473/500104) पर एक नज़र डालें, क्योंकि यह मूल रूप से आपकी आवश्यकताओं का उत्तर देता है। मैं एक डुप्लिकेट के रूप में बंद करने के लिए वोट नहीं दूंगा, हालांकि, आपका वास्तविक प्रश्न अलग है ('ऑपरेटर << 'के बारे में)। – Xeo

+2

@Xeo: मेरा वास्तविक कोड किसी भी कंटेनर को मुद्रित करने के लिए एक बहुत ही समान दृष्टिकोण का उपयोग करता है। वैसे भी, समस्या यह नहीं है कि 'ऑपरेटर <<' के साथ एक कंटेनर मुद्रित करने के लिए, यह उन चीजों के लिए वही ओवरलोड काम कैसे करें, जहां कोएनिग जो भी चाहता है वह नहीं करता है। –

उत्तर

4

मुझे लगता है कि सबसे साफ तरीका है कि आप जिस ऑपरेटरों को ओवरराइड करना चाहते हैं, उनके लिए अपने नामस्थान में पतली आवरण प्रदान करना है। आपके मामले के लिए, यह हो सकता है:

namespace ns 
{ 
    namespace wrappers 
    { 
     template<class T> 
     struct out 
     { 
      const std::set<T> &set; 

      out(const std::set<T> &set) : set(set) {} 

      friend std::ostream& operator<<(std::ostream& stream, const out &o) 
      { 
       stream << "{"; 
       bool first = true; 
       for (const T& item : o.set) 
       { 
        if (!first) 
         stream << ", "; 
        else 
         first = false; 
        stream << item; 
       } 
       stream << "}"; 
       return stream; 
      } 
     }; 
    } 

    template<class T> 
    wrappers::out<T> out(const std::set<T> &set) 
    { 
     return wrappers::out<T>(set); 
    } 
} 

तो इस तरह इसका इस्तेमाल:

std::cout << boost::format("%1%") % ns::out(x); 
+0

यह वास्तव में उपयोग किए जाने वाले समाधान के समान है। मैंने अपना समाधान भी पोस्ट किया है। –

1

आप कुछ इस तरह की कोशिश कर सकते हैं:

namespace boost // or __gnu_cxx 
{ 
    using np::operator<<; 
} 
#include <boost/format/feed_args.hpp> 
0

समस्या के रूप में पहले ही उल्लेख किया ADL की वजह से है (तर्क निर्भर देखने - अक्सर एंड्रयू कोएनिग के लिए जिम्मेदार ठहराया है, लेकिन मेरा मानना ​​है कि वह सभी दोष नहीं मिलना चाहिए) ।

यहां तक ​​कि आपके स्थानीय संदर्भ में यह एक टेम्पलेट फ़ंक्शन में काम नहीं करेगा जहां आप अपने operator<< का उपयोग करना चाहते हैं।

एक धोखा देने की चाल operator<< डालने के लिए है जिसे आप namespace std में परिभाषित करते हैं। यह verboten है, लेकिन यह आपके मामले में काम कर सकता है, लेकिन केवल अगर इसे इसके उपयोग से पहले रखा जाता है और यह समस्या हो सकती है।

और विकल्प हो सकते हैं, जैसे कि अपना स्वयं का सेट टेम्पलेट परिभाषित करना। मैं

template<typename T> using Set=std::set<T>; 

के साथ प्रयोग किया है, लेकिन एक समाधान है कि प्रदान की

using np::operator<<; 

yuyoyuppe के बिना काम नहीं मिल सका।

5

समाधान मैं वास्तव में के साथ काफी Answeror के लिए समान है चला गया है, लेकिन यह कुछ भी करने के लिए काम करता है:

namespace ns 
{ 

template <typename T> 
class FormatWrapper 
{ 
public: 
    explicit FormatWrapper(const T& x) : 
      ref(x) 
    { } 

    friend std::ostream& operator<<(std::ostream& stream, 
            const FormatWrapper<T>& self 
            ) 
    { 
     // The key is that operator<< is name lookup occurs inside of `ns`: 
     return stream << self.ref; 
    } 
private: 
    const T& ref; 
}; 

template <typename T> 
FormatWrapper<T> Formatable(const T& x) 
{ 
    return FormatWrapper<T>(x); 
} 

} 

तो उपयोग है:

boost::format("%1%") % Formatable(x); 
संबंधित मुद्दे