2012-05-30 15 views
10

İsim alanı ns içinde STL kapsayıcıları yazdırmama yardımcı olan bir işlev var. Örneğin:boost :: format ve özel std kapsayıcıları yazdırma

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

sorun oldukça açıktır: Boost fikri yok boost::format imkansız kullanarak Ancak

std::set<std::string> x = { "1", "2", "3", "4" }; 
std::cout << x << std::endl; 

:

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; 
} 

Bu doğrudan operator << ile baskı için harika çalışıyor Benim özel operator << benim isim alanı ile ilgisi olmayan türleri yazdırmak için kullanmak istiyorum. boost/format/feed_args.hpp'a using bildiriminin eklenmesi dışında, benim operator << benim için uygun bir yol var mı?

+1

Temel olarak ihtiyaçlarınıza cevap verdiğinden, bu soruya bir göz atın (http://stackoverflow.com/q/4850473/500104). Yinelemek için oy vermeyeceğim, çünkü asıl sorumunuz farklı olduğundan (operatör << 'hakkında). – Xeo

+2

@Xeo: Gerçek kodum, herhangi bir kabın yazdırılması için çok benzer bir yaklaşım kullanıyor. Her neyse, sorun 'operatör <<' ile bir kap yazdırmak değil, Koenig istediğimi yapmazlar şeyler için aynı aşırı çalışma nasıl yapılır. –

cevap

4

En temiz yolun, geçersiz kılmak istediğiniz işleçlerin her biri için kendi ad alanınızda ince bir sarıcı sağlamak olduğunu düşünüyorum. Sonra

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); 
    } 
} 

bu gibi kullanmak: Senin durumunda için, olabilir

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

Bu aslında kullandığım çözüm ile çok benzer. Çözümümü de gönderdim. –

1

Böyle bir şey deneyebilirsiniz:

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

olarak zaten belirtildiği sorun ADL taşımaktadır (argüman bağımlı arama - genellikle Andrew Koenig atfedilen, ama o tüm suç benim değil gerektiğine inanıyoruz) .

Yerel içeriğinizde bile, operator<< ürününü kullanmayı planladığınız bir şablon işlevinde çalışmaz.

Bir hile hile, namespace std içine tanımladığınız operator<< koymaktır. Bu verboten, ama sizin durumunuzda işe yarayabilir, ancak sadece kullanımdan önce konursa ve bu sorun olabilir.

Kendi Set şablonunuzu tanımlamak gibi başka seçenekler de olabilir. Ben

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

denedi ama sağlanan

using np::operator<<; 

yuyoyuppe olmadan çalışmış bir çözüm alamadım.

5

Aslında Answeror en çok benziyor gitti çözüm, ancak herhangi bir şey için çalışır:

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); 
} 

} 

Yani kullanım şöyledir: şiddetle Sugge

boost::format("%1%") % Formatable(x);