Boost tuple + transform
Is it possible to do the following.
Say my boost tuple has <std::string, T>
I would like to use std::transform + mem_fun to insert only the std::string element in a corresponding vector. Is it possible or are we required to use a loop and push_back(get<0>)...
Ie the following doesn't like to compile... (unknown types...)
result.resize(storage.size())
std::transform(storage.begin(), storage.end(), result.begin(), std::mem_fun(&boost::get<0>));
Here is an example (trying one of the comments):
#include <boost/tuple/tuple.hpp>
#include <vector>
#include <string>
#include <algorithm>
#include <boost/bind.hpp>
template <typename T>
class TestClass
{
private:
typedef boost::tuple<std::string,T> PairType;
std::vector<PairType> storage;
public:
void extract(std::vector<std::string> &result)
{
result.resize(storage.size());
std::transform(storage.begin(), storage.end(), result.begin(), boost::bind(&PairType::get<0>, _1));
}
};
int main(int argc, char**argv)
{
开发者_Python百科 TestClass<int> bb;
std::vector< std::string> result;
bb.extract(result);
return 0;
}
g++ test.cpp
test.cpp: In member function `void TestClass<T>::extract(std::vector<std::string, std::allocator<std::string> >&)':
test.cpp:17: error: expected primary-expression before ',' token
test.cpp: In member function `void TestClass<T>::extract(std::vector<std::string, std::allocator<std::string> >&) [with T = int]':
test.cpp:26: instantiated from here
test.cpp:17: error: address of overloaded function with no contextual type information
Use the member version of get
and Boost.Bind. I've tested this and it works, for what it's worth.
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
#include <boost/bind.hpp>
#include <boost/tuple/tuple.hpp>
int main()
{
typedef boost::tuple<std::string,int> T;
std::vector<T> v1;
v1.push_back(T("Blah", 23));
v1.push_back(T("Wibble", 9));
std::vector<std::string> v2;
std::transform(v1.begin(), v1.end(), std::back_inserter(v2), boost::bind(&T::get<0>, _1));
std::copy(v2.begin(), v2.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
return 0;
}
The type of the get<0>
overload that you want is:
const std::string& (*)(const boost::tuples::cons<std::string, boost::tuples::cons<int, boost::tuples::null_type> >&)
If you typedef
that to get0_fn_t
, then you can declare a pointer to this get<0>
overload with:
get0_fn_t getter_fn = &boost::tuples::get<0, std::string, boost::tuples::cons<int, boost::tuples::null_type> >;
EDIT: This program is a complete working example:
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
#include <boost/bind.hpp>
#include <boost/tuple/tuple.hpp>
int main()
{
typedef boost::tuple<std::string, int> tuple_type;
std::vector<tuple_type> tuples;
tuples.push_back(boost::make_tuple(std::string("test3"), 3));
tuples.push_back(boost::make_tuple(std::string("test0"), 0));
std::vector<std::string> strings;
typedef const std::string& (*get0_fn_t)(const boost::tuples::cons<std::string, boost::tuples::cons<int, boost::tuples::null_type> >&);
get0_fn_t getter_fn = &boost::tuples::get<0, std::string, boost::tuples::cons<int, boost::tuples::null_type> >;
std::transform(tuples.begin(), tuples.end(), std::back_insert_iterator<std::vector<std::string> >(strings), getter_fn);
std::vector<std::string>::const_iterator it, end = strings.end();
for (it = strings.begin(); it != end; ++it)
std::cout << *it << std::endl;
return EXIT_SUCCESS;
}
EDIT2: This shows how to integrate it into the TestClass
template:
template <typename T>
class TestClass
{
private:
typedef boost::tuple<std::string, T> PairType;
std::vector<PairType> storage;
public:
void extract(std::vector<std::string>& result) const
{
result.clear();
typedef const std::string& (*get0_fn_t)(const boost::tuples::cons<std::string, boost::tuples::cons<T, boost::tuples::null_type> >&);
get0_fn_t getter_fn = &boost::tuples::get<0, std::string, boost::tuples::cons<T, boost::tuples::null_type> >;
std::transform(storage.begin(), storage.end(), result.begin(), getter_fn);
}
};
精彩评论