Я пытаюсь использовать boost :: fusion :: vector. Однако у меня проблемы с очень простой проблемой.
#include <iostream>
#include <string>
#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/algorithm.hpp>
using namespace std;
struct A{
template <class T>
void operator()(const T& t) {
x++;
cout << t << endl;
}
int x = 0;
};
int main(){
A a;
boost::fusion::vector<int, int, int> tuple{3,4,5};
boost::fusion::for_each(tuple, a);
}
Обратите внимание, что operator()
из struct A
модифицирует x
в struct A
,
gcc 4.7.2 предупреждает, что … \ include \ boost \ fusion \gorithm \ iteration \ detail \ for_each.hpp: 77: ошибка: передача ‘const A’ в качестве ‘this’ аргумента ‘void A :: operator () ( const T&) [with T = int] ‘отбрасывает квалификаторы [-fpermissive]
Есть ли решение для этого?
Ну, я не использовал boost :: fusion, но из сообщения об ошибке и пример из документов, Кажется, что for_each
ожидает постоянный объект. То есть operator()
должен быть постоянным. Однако вы не сможете изменить объект.
Попробуй это:
void operator()(const T& t) const {
cout << t << endl;
}
Редактировать:
Я проверил источники (v. 1.53) и объявление for_each(Sequence& seq, F const& f)
, Так что на самом деле нет способа изменить сам объект. Единственные варианты, которые я вижу:
либо используйте статические переменные: static int x;
или используйте указатели:
struct A {
template <class T>
void operator()(const T& t) const {
(*x)++;
std::cout << t << std::endl;
}
int* x;
};
int main()
{
A a;
a.x = new int;
*(a.x) = 0;
//...
В этом случае будьте осторожны с преодолением A
экземпляры, так как все указатели будут указывать на одно и то же место.
Более простой и лучший способ сделать это — использовать fusion :: fold:
#include <iostream>
#include <boost/fusion/algorithm/iteration/fold.hpp>
#include <boost/fusion/include/fold.hpp>
namespace detail {
struct A {
typedef int result_type;
template<typename T1, typename T2>
int operator()( const T1& t1, const T2& t2 ) const {
std::cout << t1 << "," << t2 << std::endl;
return t1 + 1;
}
};
}
int main() {
boost::fusion::vector<int, int, int> tuple{3,4,5};
boost::fusion::fold(tuple, 0, detail::A());
}
За исключением любых синтаксических ошибок, это должно привести к:
0,3
1,4
2,5
Решение представлено в документации boost :: phoenix :: lambda.
Секрет в том, чтобы делать различные вычисления в лямбда-функции вне вашего функтора.
#include <iostream>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <boost/phoenix/core.hpp>
#include <boost/phoenix/operator.hpp>
#include <boost/phoenix/operator/arithmetic.hpp>
#include <boost/phoenix/scope/lambda.hpp>
#include <boost/phoenix/scope/local_variable.hpp>
#include <boost/phoenix/function.hpp>
#include <boost/phoenix/fusion.hpp>
namespace detail {
struct A_impl {
template<typename T1, typename T2>
void operator()( const T1& t1, const T2& t2 ) const {
std::cout << t2 << "," << t1 << std::endl;
}
};
boost::phoenix::function<A_impl> const A = A_impl();
}
int main() {
namespace phx = boost::phoenix;
using boost::phoenix::arg_names::arg1;
using boost::phoenix::local_names::_a;
boost::fusion::vector<int, int, int> tuple{3,4,5};
boost::fusion::for_each(tuple, phx::lambda( _a = 0 )[detail::A(arg1,_a++)]);
}
За исключением любых синтаксических ошибок, это должно привести к:
0,3
1,4
2,5