2014-01-15 71 views
2

我正在嘗試使用Boost.Assign填充boost::property_tree::ptree。所以,我得到了以下工作得很好:Boost.Bind返回類型

namespace bpt = boost::property_tree; 
bpt::ptree pt; 
boost::assign::make_list_inserter 
    (boost::bind(&bpt::ptree::put<std::string>, pt, _1, _2)) 
     ("one.two.three", "four") 
     ("one.two.five", "six"); 

然而,當我試圖讓這段代碼更好看,它不能編譯:

typedef bpt::ptree& (bpt::ptree::*PutType) 
    (const bpt::path_of<std::string>::type&, const std::string &); 

PutType Put = &bpt::ptree::put<std::string>; 

inline boost::assign::list_inserter<PutType> put(bpt::ptree &pt) { 
    PutType putFunction = boost::bind(Put, pt, _1, _2); // !!! compile error 
    return boost::assign::make_list_inserter(putFunction); 
} 

//and use it like: 
put(pt) 
    ("one.two.three", "four") 
    ("one.two.five", "six"); 

錯誤消息

SomeFile.cpp: In function ‘boost::assign::list_inserter<boost::property_tree::ptree& (boost::property_tree::ptree::*)(const boost::property_tree::string_path<std::string, boost::property_tree::id_translator<std::string > >&, const std::string&), boost::assign_detail::forward_n_arguments> put(boost::property_tree::ptree&)’:

SomeFile.cpp:42: error: cannot convert ‘boost::_bi::bind_t<boost::property_tree::ptree&, boost::_mfi::mf2<boost::property_tree::ptree&, boost::property_tree::ptree, const boost::property_tree::string_path<std::string, boost::property_tree::id_translator<std::string > >&, const std::string&>, boost::_bi::list3<boost::_bi::value<boost::property_tree::ptree >, boost::arg<1>, boost::arg<2> > >’ to ‘boost::property_tree::ptree& (boost::property_tree::ptree::*)(const boost::property_tree::string_path<std::string, boost::property_tree::id_translator<std::string > >&, const std::string&)’ in initialization

使代碼起作用的最佳方式是什麼?

回答

3

你必須在代碼中幾個錯誤:

  1. boost::bind()存儲由值約束參數,使boost::bind(&bpt::ptree::put<std::string>, pt, _1, _2)使得pt副本,並填補了這個副本。改爲傳遞指針:boost::bind(&bpt::ptree::put<std::string>, &pt, _1, _2)或使用boost::ref(pt)
  2. boost::bind返回的對象不能轉換爲指針類型,這就是爲什麼PutType putFunction = boost::bind(Put, pt, _1, _2);無法編譯。

在C++ 03沒有auto關鍵字,你不能輕易捕捉類型boost::bindboost::list_inserter。你可以把兩者的結果都打包成boost::function<>,但在我看來這太過粗暴了。

但是你可以實現C++ 03與平原所需的語法:

namespace bpt = boost::property_tree; 

struct PtreeInserter 
{ 
    bpt::ptree* pt; 

    PtreeInserter(bpt::ptree& pt) : pt(&pt) {} 

    template<class A1, class A2> 
    PtreeInserter const& operator()(A1 a1, A2 a2) const { 
     pt->put(a1, a2); 
     return *this; 
    } 
}; 

int main() { 
    bpt::ptree pt; 
    typedef PtreeInserter put; 
    put(pt) 
     ("one.two.three", "four") 
     ("one.two.five", "six"); 
} 
+0

謝謝(+1)。你知道嗎,我可以如何重寫代碼來使它工作? – Loom

+0

再次感謝您。爲什麼'boost :: function'很重要?是否有一些表現懲罰? – Loom

+1

@Loom'boost :: function'在構造和複製時涉及內存分配;和調用時指針間接。它爲一些簡單的情況進行了優化,以避免內存分配,但這些情況並非如此。 –