![](/img/trans.png)
[英]Transform a std::vector of boost.asio::ip::address via boost::algorithm::join and boost::adaptors::transformed
[英]boost::join and boost::transformed
我想用boost來加入字符串“,”。 但我有一個shared_ptr的向量,我需要將其轉換為字符串。
(這樣做的愚蠢方法是使用boost :: transform將我的共享指針轉換為字符串向量)。 但我想做這樣的事情。
注意:我使用的是VS2012(以及用於Linux版本的gcc 4.5.3)並且增強了1.48.0
C ++代碼。
std::string A::returnConcatString() const
{
return boost::algorithm::join( sharedPtrList() | boost::adaptors::transformed(
[](B::ConstPtr obj )->std::string
{
return ( boost::format( "%s:%s" ) % obj->string1() % obj->string2() ).str();
} ),
",");
}
(BTW如果我使用匿名函數而不是使用string2()會發生什么?)
HPP代碼。
class A
{
public:
/***code***/
vector< B::ConstPtr > sharedPtrList() const;
std::string returnConcatString() const;
}
class B
{
public:
typedef boost::shared_ptr<const B> ConstPtr;
std::string string1() const;
std::string string2() const;
}
有一個更好的方法嗎? 誰能幫助我理解我的問題?
另外,我遇到了這個鏈接http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3594.html (這正是我想模仿的)
當我編譯這段代碼時,我收到一個錯誤。
C:\temp\tools\Windows\Boost\1.48.0\boost/utility/result_of.hpp(79): error C2903: 'result' : symbol is neither a class template nor a function template
C:\temp\tools\Windows\Boost\1.48.0\boost/utility/result_of.hpp(87) : see reference to class template instantiation 'boost::detail::result_of_nested_result<F,FArgs>' being compiled
with
[
F=balh::`anonymous-namespace'::<lambda0>,
FArgs=balh::`anonymous-namespace'::<lambda0> (const boost::shared_ptr<const balh::B> &)
]
C:\temp\tools\Windows\Boost\1.48.0\boost/utility/detail/result_of_iterate.hpp(33) : see reference to class template instantiation 'boost::detail::tr1_result_of_impl<F,FArgs,HasResultType>' being compiled
with
[
F=balh::`anonymous-namespace'::<lambda0>,
FArgs=balh::`anonymous-namespace'::<lambda0> (const boost::shared_ptr<const balh::B> &),
HasResultType=false
]
C:\temp\tools\Windows\Boost\1.48.0\boost/utility/detail/result_of_iterate.hpp(81) : see reference to class template instantiation 'boost::tr1_result_of<F>' being compiled
with
[
F=balh::`anonymous-namespace'::<lambda0> (const boost::shared_ptr<const balh::B> &)
]
C:\temp\tools\Windows\Boost\1.48.0\boost/mpl/eval_if.hpp(41) : see reference to class template instantiation 'boost::result_of<F>' being compiled
編輯 :感謝[utnapistim]的想法。 我現在正在使用它。 但我真的想寫一個單行:)。
我最終這樣做了。
std::string ret;
std::for_each ( array.begin(), array.end(), [&ret](B::ConstPtr firmware)
{
ret.append( ( boost::format( "[%s:%s]" ) % firmwareTypeToString( firmware->firmwareType() ) % firmware->version() ).str() );
}
);
我用這個:
/*
* File: ostream_join_iterator.hpp
* Author: utnapistim :)
*
* Created on July 13, 2013, 1:14 AM
*/
#ifndef OSTREAM_JOIN_ITERATOR_HPP
#define OSTREAM_JOIN_ITERATOR_HPP
/**
* @brief Implements join functionality directing into an ostream
*
* This class provides an iterator for writing into an ostream.
* The type T is the only type written by this iterator and there must
* be an operator << (T) defined.
*
* @remarks This class implements functionality similar to
* std::ostream_iterator except it does not print a separator after the
* last element.
*
* @param Tp The type to write to the ostream.
* @param CharT The ostream char_type.
* @param Traits The ostream char_traits.
*/
template<typename T, typename C=char, typename Tr=std::char_traits<C> >
class ostream_join_iterator
: public std::iterator<std::output_iterator_tag, void, void, void, void>
{
public:
typedef C char_type;
typedef Tr traits_type;
typedef std::basic_string<C, Tr> splitter_type;
typedef std::basic_ostream<C, Tr> ostream_type;
private:
ostream_type *out_;
splitter_type splitter_;
bool at_first_;
public:
ostream_join_iterator(ostream_type& out)
: out_{&out}
, splitter_{}
, at_first_{true}
{
}
/**
* Construct from an ostream.
*
* @remarks The delimiter is not copied, and thus must not be destroyed
* while this iterator is in use.
*
* @param out Underlying ostream to write to.
* @param splitter CharT delimiter string to insert.
*/
ostream_join_iterator(ostream_type& out, const char_type* splitter)
: out_{&out}
, splitter_{splitter}
, at_first_{true}
{
}
/// Copy constructor.
ostream_join_iterator(const ostream_join_iterator& other)
: out_{other.out_}
, splitter_{other.splitter_}
, at_first_{other.at_first_}
{
}
ostream_join_iterator& operator=(const T& value)
{ // add separator before the value, if not at first element
if((not splitter_.empty()) and (not at_first_))
*out_ << splitter_;
*out_ << value;
at_first_ = false;
return *this;
}
ostream_join_iterator& operator=(ostream_join_iterator temp)
{
using std::swap;
swap(out_, temp.out_);
swap(splitter_, temp.splitter_);
swap(at_first_, temp.at_first_);
return *this;
}
ostream_join_iterator&
operator*() {
return *this;
}
ostream_join_iterator&
operator++() {
return *this;
}
ostream_join_iterator&
operator++(int) {
return *this;
}
};
template <typename T> using join = ostream_join_iterator<T>;
template <typename T> using wjoin = ostream_join_iterator<T, wchar_t>;
#endif /* OSTREAM_JOIN_ITERATOR_HPP */
用法:
using namespace std;
ostringstream sql;
sql << "SELECT ";
transform(fields_.begin(), fields_.end(), join<string>{sql, ", "},
[](const field& f) { return f.escaped_name(); });
sql << " FROM " << name_;
變換調用可以很容易地調整到便利功能中。
我只是這樣寫:
std::string returnConcatString() const {
std::ostringstream os;
for(auto& b : sharedPtrList)
os << b->string1() << ':' << b->string2() << ',';
auto s = os.str();
if (!s.empty())
s.resize(s.size()-1);
return s; // moves
}
令人驚訝的是,編譯時間更好,運行時將比您的代碼實現的要好很多 。
如果你真的關心性能,我會建議Boost Karma:
std::string returnConcatString() const {
if (sharedPtrList.empty())
return {};
std::string result;
result.reserve(20 * sharedPtrList.size()); // average length preallocate?
auto out = back_inserter(result);
namespace k = boost::spirit::karma;
for(auto& b : sharedPtrList)
k::generate(out, k::string << ':' << k::string << ',', b->string1(), b->string2());
result.resize(result.size()-1);
return result; // moves
}
性能比較:
正如您所看到的, stringstream
方法只對小型集合stringstream
。
原始數據和基准代碼
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.