Повысить кортеж + преобразовать - PullRequest
4 голосов
/ 13 января 2011

Можно ли сделать следующее.

Скажи, что мой буст-кортеж имеет <std::string, T>

Я хотел бы использовать std :: transform + mem_fun для вставки только элемента std :: string в соответствующий вектор. Возможно ли это или мы должны использовать цикл и push_back (get <0>) ...

Т.е. следующее не любит компилировать ... (неизвестные типы ...)

result.resize(storage.size())
std::transform(storage.begin(), storage.end(), result.begin(), std::mem_fun(&boost::get<0>));

Вот пример (пробует один из комментариев):

#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)
{

    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

Ответы [ 2 ]

3 голосов
/ 13 января 2011

Используйте версию участника get и Boost.Bind.Я проверил это, и это работает, для чего это стоит.

#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;
}
1 голос
/ 13 января 2011

Тип требуемой перегрузки get<0>:

const std::string& (*)(const boost::tuples::cons<std::string, boost::tuples::cons<int, boost::tuples::null_type> >&)

Если вы typedef это get0_fn_t, то вы можете объявить указатель на эту get<0> перегрузку:

get0_fn_t getter_fn = &boost::tuples::get<0, std::string, boost::tuples::cons<int, boost::tuples::null_type> >;

РЕДАКТИРОВАТЬ: Эта программа является полным рабочим примером:

#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: Здесь показано, как интегрировать его в шаблон TestClass:

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);
    }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...