Conceptual issue with range based iteration over multiple std containers using boost - c++

I have a function which "zips" multiple containers for range based foor loop iteration. (taken from a another Stack Overflow post)
template<class... Conts>
auto zip_range(Conts&... conts)
-> decltype(boost::make_iterator_range(boost::make_zip_iterator(boost::make_tuple(conts.begin()...)),
boost::make_zip_iterator(boost::make_tuple(conts.end()...)))) {
return {boost::make_zip_iterator(boost::make_tuple(conts.begin()...)),
boost::make_zip_iterator(boost::make_tuple(conts.end()...))};
}
I can use this function like so:
std::vector<int> x({1,2,3});
std::vector<int> y({4,5,6});
for ( auto const& entries : zip_range(x,y) ) {
std::cout << entries.get<0>() << " " << entries.get<1>() << std::endl;
}
And get expected behavior:
1 4
2 5
3 6
If I try to define a function which takes two std::initizalizer_list arguments, passes them to a vector, and tries to loop:
template <class T1, class T2>
void foo(const std::initializer_list<T1>& il1,
const std::initializer_list<T2>& il2) {
std::vector<T1> v1(il1);
std::vector<T2> v2(il2);
for ( auto const& zipitr : zip_range(v1,v2) ) {
std::cout << zipitr.get<0>() << " " << zipitr.get<1>() << std::endl;
}
}
I get a compilation error that isn't very helpful:
testing.cpp: In function ‘void foo(const std::initializer_list<_Tp>&, const std::initializer_list<T2>&)’:
testing.cpp:34:32: error: expected primary-expression before ‘)’ token
std::cout << zipitr.get<0>() << " " << zipitr.get<1>() << std::endl;
^
testing.cpp:34:58: error: expected primary-expression before ‘)’ token
std::cout << zipitr.get<0>() << " " << zipitr.get<1>() << std::endl;
Why am I unable to do this? (much less go straight to giving the initializer lists to the function zip_range)

The type of zipitr is dependent on T1 and T2 and that type has a nested member function template get. So to tell the compiler get is a dependent function template, you need to add the template keyword immediately before it.
std::cout << zipitr.template get<0>() << " " << zipitr.template get<1>() << std::endl;
// ^^^^^^^^ ^^^^^^^^
Read this answer for details of why this is needed.
An alternative that avoids the template keyword is to use the boost::get free function.
std::cout << boost::get<0>(zipitr) << " " << boost::get<1>(zipitr) << std::endl;
Your zip_range function can be simplified (or replaced) using boost::combine
#include <boost/range/combine.hpp>
template<class... Conts>
auto zip_range(Conts&... conts)
-> decltype( boost::combine(conts...) )
{
return boost::combine(conts...);
}
Live demo
The reason you can't pass {1,2,3} directly to zip_range is that a braced-init-list is not an expression, so it doesn't have a type, which means template argument deduction cannot work.
auto has a special rule to deal with them that allows it to deduce the type as std::initializer_list<T>, so the following works:
auto l1 = {1,2,3};
auto l2 = {4,5,6};
for ( auto const& zipitr : zip_range(l1,l2) ) {
std::cout << boost::get<0>(zipitr) << " " << boost::get<1>(zipitr) << std::endl;
}
Live demo

Related

Simpler logger function using std::stringstream

I'm trying to write a simple logging function which can handle different types in this format:
LOG("This is one type: " << one_type << " and here is a different type: " << diff_type);
I've been looking at the examples here:
How to use my logging class like a std C++ stream?
stringstream with recursive variadic function?
and this is what I came up with:
#include <iostream>
#include <sstream>
void LOG(std::stringstream& ss)
{
std::cout << ss.str() << std::endl;
}
However, even when I just do:
LOG("Some text");
I get the error:
could not convert ‘(const char*)"Some text"’ from ‘const char*’ to ‘std::stringstream’ {aka ‘std::__cxx11::basic_stringstream<char>’}
How can I implement this?
A common way to solve this is to make LOG a macro that just does text substitution instead. You could define a LOG macro like
#define LOG(to_log) \
do \
{ \
std::cout << to_log << std::endl; \
} while (false)
and then
LOG("This is one type: " << one_type << " and here is a different type: " << diff_type);
would get expanded to
do
{
std::cout << "This is one type: " << one_type << " and here is a different type: " << diff_type << std::endl;
} while (false);
template <typename ... T>
void log(T const& ... t)
{
( std::cout << ... << t );
// maybe want to add a newline?
std::cout << std::endl; // note: '\n' just adds it,
// std::endl flushes the stream...
}
would allow to log (to console!) as:
log("this is an int: ", 1210, " and this is a double: ", 10.12);
Note the commas instead of the stream operator (<<)...
If you want to log to arbitrary streams you might need to add it as yet another parameter (/*...*/ void log(std::ostream& s, T const&... t)) or you might (among other solutions) initialise some singleton that you access from within the logging function:
void initialiseLogging(std::ostream& s)
{
Logger::instance().initialize(s);
}
template <typename ... T>
void log(T const& ... t)
{
// assumes returning a reference:
( Logger::instance().stream() << ... << t );
}
Above variant assumes initialisation being required and logging without yielding undefined behaviour (needs to be documented!). If you want to be able to log without you need to change:
{
// now assuming a pointer being returned!
auto s = Logger::instance().stream();
// variant 1: log to nowhere if not initialised:
if(s)
{
( *s << ... << t );
}
// variant 2: default logging to console
s = s ? s : &std::cout;
( *s << ... << t );
}

How to perfectly forward `*this` object inside member function

Is it possible to perfectly forward *this object inside member functions? If yes, then how can we do it? If no, then why not, and what alternatives do we have to achieve the same effect.
Please see the code snippet below to understand the question better.
class Experiment {
public:
double i, j;
Experiment(double p_i = 0, double p_j = 0) : i(p_i), j(p_j) {}
double sum() { return i + j + someConstant(); }
double someConstant() && { return 10; }
double someConstant() & { return 100; }
};
int main() {
Experiment E(3, 5);
std::cout << std::move(E).sum() << "\n"; // prints: 108
std::cout << E.sum() << "\n"; // prints: 108
}
This output seems expected if we consider that *this object inside the member function double sum() is always either an lvalue or xvalue (thus a glvalue) . Please confirm if this is true or not.
How can we perfectly forward *this object to the member function call someConstant() inside the double sum() member function?
I tried using std::forward as follows:
double sum() {
return i + j + std::forward<decltype(*this)>(*this).someConstant();
}
But this did not have any effect, and double someConstant() & overload is the one always being called.
This is not possible in C++11 without overloading sum for & and && qualifiers. (In which case you can determine the value category from the qualifier of the particular overload.)
*this is, just like the result of any indirection, a lvalue, and is also what an implicit member function call is called on.
This will be fixed in C++23 via introduction of an explicit object parameter for which usual forwarding can be applied: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0847r7.html
One would think that std::forward() would preserve lvalue references but it doesn't in non-template contexts, as the example below shows.
Both call_f()& and call_f()&& call f()&&. std::forward<Experiment>(*this) in a non-template function returns an rvalue reference regardless of the value category of the argument.
Note how this works differently from a template function, member or not (I made the member function static because it receives a "this reference" as an explicit parameter) . Both forward lvalue references "properly" (the last 4 calls).
#include<iostream>
#include<utility>
#include<string>
struct Experiment
{
public:
std::string f()&& { return "f()&&"; }
std::string f()& { return "f()&"; }
std::string call_f()&& { std::cout << "call_f()&& "; return std::forward<Experiment>(*this).f(); }
// I need this function because it is not a template function
std::string call_f()& { std::cout << "call_f()& "; return std::forward<Experiment>(*this).f(); }
template<class T = Experiment>
static std::string E_t_call_f(T&& t) { std::cout << "E_t_call_f(T&& t) "; return std::forward<T>(t).f(); }
};
template<class T>
std::string t_call_f(T&& t) { std::cout << "t_call_f(T&& t) "; return std::forward<T>(t).f(); }
int main()
{
Experiment E;
std::cout << "E.f(): " << E.f() << '\n';
std::cout << "move(E).f(): " << std::move(E).f() << '\n';
std::cout << '\n';
std::cout << "E.call_f(): " << E.call_f() << '\n';
std::cout << "move(E).call_f(): " << std::move(E).call_f() << '\n';
std::cout << '\n';
std::cout << "t_call_f(E): " << t_call_f(E) << '\n';
std::cout << "t_call_f(std::move(E)): " << t_call_f(std::move(E)) << '\n';
std::cout << '\n';
std::cout << "E::E_t_call_f(E): " << Experiment::E_t_call_f(E) << '\n';
std::cout << "E::E_t_call_f(std::move(E)): " << Experiment::E_t_call_f(std::move(E)) << '\n';
}
In the resulting output it is the third line that's surprising: The type of std::forward<Experiment>(*this) for an lvalue reference to *this is an rvalue reference.
E.f(): f()&
move(E).f(): f()&&
call_f()& E.call_f(): f()&&
call_f()&& move(E).call_f(): f()&&
t_call_f(T&& t) t_call_f(E): f()&
t_call_f(T&& t) t_call_f(std::move(E)): f()&&
E_t_call_f(T&& t) E::E_t_call_f(E): f()&
E_t_call_f(T&& t) E::E_t_call_f(std::move(E)): f()&&

declaration inside if condition [duplicate]

I was experimenting with C++17 feature std::optional
The optional return type is std::optional<std::pair<int, int>>. I call the
sum_pair function in print_answer function and wanted a optional print.
In print_answer function I wanted to check whether the required pair holds something to show.
like in the example given in: optional-returning factory functions are usable as conditions of while and if
Following is the code: here is it live with error
#include <iostream>
#include <vector>
#include <unordered_map>
#include <optional>
typedef std::optional<std::pair<int, int>> returnType;
// following algorithum works fine: just to show,
// how I have used the std::optional
returnType sum_pair(const std::vector<int>& vec, const int sum)
{
std::unordered_map<int, int> compIndexMap;
int index = 0;
for(const int& ele: vec)
{
if(auto check = compIndexMap.find(sum - ele); check != compIndexMap.cend())
return returnType{std::make_pair(check->second, index)};
compIndexMap.emplace(sum - ele, index);
++index;
}
return std::nullopt;
}
// problem is here:
void print_answer(const std::vector<int>& vec, const int sum)
{
// if I uncomment the if-else, everything works
/*if*/(auto Pair = sum_pair(vec, sum) )?
std::cout << "Resulting indexes are: " << Pair->first << " " << Pair->second << std::endl: //;
//else
std::cout << "Nothing found!\n";
}
int main()
{
std::vector<int> vec0{ 1,3,2,8 };
const int sum = 8;
print_answer(vec0, sum);
return 0;
}
When I use the if-else statement in the following format
(condion) ? print something: print something else;
I get the following two errors. (used GCC 7.1)
||=== Build: Debug in MyTestProgram (compiler: GNU GCC Compiler) ===|
|25|error: expected primary-expression before 'auto'|
|25|error: expected ')' before 'auto'|
Can somebody explain, why I need to use if-else, but not with "operator ?" ?
if(auto Pair = sum_pair(vec, sum) )
std::cout << "Resulting indexes are: " << Pair->first << " " << Pair->second << std::endl;
else
std::cout << "Nothing found!\n";
this is valid C++. You are allowed to put a declaration in the opening condition of an if clause.
(auto Pair = sum_pair(vec, sum) )?
std::cout << "Resulting indexes are: " << Pair->first << " " << Pair->second << std::endl
:
std::cout << "Nothing found!\n";
this is not valid C++. Declarations are not expressions. There are places where expressions are allowed, but declararions are not. The left hand side of ?, the trinary operator, is one of them.

C++17 std::optional error: expected primary-expression before 'auto'

I was experimenting with C++17 feature std::optional
The optional return type is std::optional<std::pair<int, int>>. I call the
sum_pair function in print_answer function and wanted a optional print.
In print_answer function I wanted to check whether the required pair holds something to show.
like in the example given in: optional-returning factory functions are usable as conditions of while and if
Following is the code: here is it live with error
#include <iostream>
#include <vector>
#include <unordered_map>
#include <optional>
typedef std::optional<std::pair<int, int>> returnType;
// following algorithum works fine: just to show,
// how I have used the std::optional
returnType sum_pair(const std::vector<int>& vec, const int sum)
{
std::unordered_map<int, int> compIndexMap;
int index = 0;
for(const int& ele: vec)
{
if(auto check = compIndexMap.find(sum - ele); check != compIndexMap.cend())
return returnType{std::make_pair(check->second, index)};
compIndexMap.emplace(sum - ele, index);
++index;
}
return std::nullopt;
}
// problem is here:
void print_answer(const std::vector<int>& vec, const int sum)
{
// if I uncomment the if-else, everything works
/*if*/(auto Pair = sum_pair(vec, sum) )?
std::cout << "Resulting indexes are: " << Pair->first << " " << Pair->second << std::endl: //;
//else
std::cout << "Nothing found!\n";
}
int main()
{
std::vector<int> vec0{ 1,3,2,8 };
const int sum = 8;
print_answer(vec0, sum);
return 0;
}
When I use the if-else statement in the following format
(condion) ? print something: print something else;
I get the following two errors. (used GCC 7.1)
||=== Build: Debug in MyTestProgram (compiler: GNU GCC Compiler) ===|
|25|error: expected primary-expression before 'auto'|
|25|error: expected ')' before 'auto'|
Can somebody explain, why I need to use if-else, but not with "operator ?" ?
if(auto Pair = sum_pair(vec, sum) )
std::cout << "Resulting indexes are: " << Pair->first << " " << Pair->second << std::endl;
else
std::cout << "Nothing found!\n";
this is valid C++. You are allowed to put a declaration in the opening condition of an if clause.
(auto Pair = sum_pair(vec, sum) )?
std::cout << "Resulting indexes are: " << Pair->first << " " << Pair->second << std::endl
:
std::cout << "Nothing found!\n";
this is not valid C++. Declarations are not expressions. There are places where expressions are allowed, but declararions are not. The left hand side of ?, the trinary operator, is one of them.

Using Eigen::VectorXd (Eigen 3.3.4) as a state type in boost::numeric::odeint (Boost 1.65.1)

During my work, it would be a requirement for me to use Eigen::VectorXcd as state type, to solve a huge linear ODE system. In that project, the matrix in the ODE system is sparse. Multiplying a it with a dense vector can be computed in parallel in a simple way using Eigen. However, I have faced some problems in that situation that I will tell in details below. Currently I am applying a not-so efficient solution, namely, I use arma::cx_vec as state type, and declare the matrix corresponding the ode arma::cx_mat, which is a dense matrix type. Unfortunately, sparse-matrix-dense vector multiplication cannot be parallelized with Armadillo since it supports only the single-threaded version of SuperLU. According to my experience, in my specific case, sparse matrix-dense vector multiplication is three times faster than dense matrix-dense vector multiplication. Since a single running lasts for tens or hundreds of hours even when using 20 CPU cores simultaneously, it would be highly required for me to be able to use the Eigen library along with boost::odeint to gain a factor of three in runtime.
For testing purposes, I tried to use Eigen::VectorXd as a state type. I have also found very similar situations, see: Using Boost::odeint with Eigen::Matrix as a state vector or using several eigen matrices as statetypes in boost/odeint. However, none of the solutions worked for me. In my real project, I have to use the Bulirsch-Stoer method to integrate my ODE system since high precision and therefore error control is necessary for me. Below I will post my test code, corresponding to Eigen::VectorXd state type. As you can see, for first, I followed the steps described in the boost::odeint documentation: I defined my state vector resizeable and overloaded the mathematical operators used by the vector space algebra of the controlled stepper. After these steps, the code still did not compile, overloading of the addition operator for adding vectors to scalars was also necessary. Here is my code:
#include <iostream>
#include <vector>
#include <complex>
#include <Eigen/Eigen>
#include <boost/numeric/odeint.hpp>
namespace boost {
namespace numeric {
namespace odeint {
template<>
struct is_resizeable<Eigen::VectorXd>
{
typedef boost::true_type type;
static const bool value = type::value;
};
template<>
struct same_size_impl<Eigen::VectorXd, Eigen::VectorXd>
{
static bool same_size(const Eigen::VectorXd& v1, const Eigen::VectorXd& v2)
{
std::cout << "same_size: " << v1.transpose() << " and " << v2.transpose() << std::endl;
std::cout << "same_size: " << v1.rows() << " == " << v2.rows() << std::endl;
return v1.rows() == v2.rows();
}
};
template<>
struct resize_impl<Eigen::VectorXd, Eigen::VectorXd>
{
static void resize(Eigen::VectorXd& v1, const Eigen::VectorXd& v2)
{
std::cout << "resize_impl: " << v1.transpose() << " and " << v2.transpose() << std::endl;
std::cout << "resize_impl: (" << v1.rows() << " x " << v1.cols() << ") to (" << v2.rows() << " x " << v2.cols() << ")" << std::endl;
v1.conservativeResize(v2.size());
std::cout << "resize_impl: new size: " << v1.rows() << " x " << v1.cols() << std::endl;
}
};
template<>
struct vector_space_norm_inf<Eigen::VectorXd>
{
typedef double result_type;
double operator()(const Eigen::VectorXd& v) const
{
std::cout << "vector_space_norm_inf(" << v.transpose() << ") = " << v.lpNorm<Eigen::Infinity>() << std::endl;
return v.lpNorm<Eigen::Infinity>();
}
};
}
}
}
namespace Eigen {
//VectorXd operator*(const double& a, const VectorXd& v)
//{
// std::cout << a << "*(" << v.transpose() << ") = " << a*(v.transpose()) << std::endl;
// return a*v;
//}
//
//VectorXd operator*(const VectorXd& v, const double& a)
//{
// std::cout << "(" << v.transpose() << ")*" << v.transpose() << " = " << a*(v.transpose()) << std::endl;
// return a*v;
//}
//
//VectorXd& operator*=(const double& a, VectorXd& v)
//{
// std::cout << "operator*=(const double& a, VectorXd& v): (" << v.transpose() << ") *= " << a << ": ";
// v *= a;
// std::cout << v.transpose() << std::endl;
// return v;
//}
//
//VectorXd& operator*=(VectorXd& v, const double& a)
//{
// std::cout << "operator*=(VectorXd& v, const double& a): (" << v.transpose() << ") *= " << a << ": ";
// v *= a;
// std::cout << v.transpose() << std::endl;
// return v;
//}
//
//VectorXd& operator+=(VectorXd& v1, const VectorXd& v2)
//{
// std::cout << "(" << v1.transpose() << ") += (" << v2.transpose() << "): ";
// v1 += v2;
// std::cout << v1.transpose() << std::endl;
// return v1;
//}
VectorXd operator/(const VectorXd& v1, const VectorXd& v2)
{
const char* sizeeq;
if(v1.size() == v2.size())
sizeeq = "True";
else
sizeeq = "FALSE!";
std::cout << "operator/: size check: " << v1.size() << " ?= " << v2.size() << ": " << sizeeq << std::endl;
VectorXd result(v1.cwiseQuotient(v2));
std::cout << "(" << v1.transpose() << ") / (" << v2.transpose() << ") = " << result.transpose() << std::endl;
return result;
}
VectorXd operator+(double d, const VectorXd& v)
{
std::cout << d << " + (" << v.transpose() << ") = " << d+v.transpose() << std::endl;
return d+v;
}
VectorXd operator+(const VectorXd& v, double d)
{
std::cout << "(" << v.transpose() << ") + " << d << " = " << d+v.transpose() << std::endl;
return d+v;
}
VectorXd abs(const VectorXd& v)
{
std::cout << "|(" << v.transpose() << ")| = " << v.cwiseAbs().transpose() << std::endl;
return v.cwiseAbs();
}
}
typedef Eigen::VectorXd state_type;
typedef Eigen::MatrixXd coeff_matrix_type;
class lin_diff_eq
{
public:
lin_diff_eq(coeff_matrix_type gam): m_gam(gam) {}
coeff_matrix_type get_matrix() const { return m_gam; }
void operator()(const state_type& x, state_type& dxdt, const double t)
{
std::cout << "size: " << x.size() << std::endl;
std::cout << x.transpose() << std::endl;
dxdt = m_gam*x;
}
private:
coeff_matrix_type m_gam;
};
using namespace boost::numeric::odeint;
int main()
{
coeff_matrix_type A = coeff_matrix_type(2,2);
state_type x = state_type(2);
double epsabs = 1e-4;
double epsrel = 1e-4;
A << 0, 1,
-2, 0;
x << 1, 0;
lin_diff_eq lde(A);
std::cout << lde.get_matrix() << std::endl;
integrate_adaptive(bulirsch_stoer<state_type, double, state_type, double, vector_space_algebra>(epsabs, epsrel), lin_diff_eq(A), x, 0.0, 1.0, 0.1);
}
All these steps made my code compile, however, during runtime my program crashes with segmentation fault. As you can see, I overloaded all the operators such that they produce some kind of a very simple log, I couldn't figure out how to produce a more detailed log to locate exactly where and why the segmentation fault occurs. According to the boost::odeint documentation, this can happen during runtime when the vector space algebra doesn't know how to resize the vectors, but I already defined how to do it. On my computer, it can be seen that boost::odeint generates some internal states, resizes them correctly, computes elementwise abs() correctly, but after that it crashes.
The next thing I tried was to use the support to Eigen provided by the boost::odeint developers. In this case, I did not use any of the template specializations and the operator overloads provided above, but instead, I included
boost/numeric/odeint/external/eigen/eigen_algebra.hpp
after including odeint.hpp. The code did not compile, I got the following error messages:
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp|35|error: ‘scalar_add_op’ in namespace ‘Eigen::internal’ does not name a type|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp|35|error: expected template-argument before ‘<’ token|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp|35|error: expected ‘>’ before ‘<’ token|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp|37|error: wrong number of template arguments (1, should be 2)|
/usr/local/include/Eigen/src/Core/util/ForwardDeclarations.h|91|error: provided for ‘template<class UnaryOp, class MatrixType> class Eigen::CwiseUnaryOp’|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp|38|error: expected ‘::’ before ‘operator’|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp|38|error: expected identifier before ‘operator’|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp||In function ‘const int Eigen::operator+(const Eigen::MatrixBase<Derived>&, const typename Eigen::internal::traits<T>::Scalar&)’:|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp|41|error: ‘scalar_add_op’ in namespace ‘Eigen::internal’ does not name a type|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp|41|error: expected template-argument before ‘<’ token|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp|41|error: expected ‘>’ before ‘<’ token|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp|43|error: wrong number of template arguments (1, should be 2)|
/usr/local/include/Eigen/src/Core/util/ForwardDeclarations.h|91|error: provided for ‘template<class UnaryOp, class MatrixType> class Eigen::CwiseUnaryOp’|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp|43|error: expected ‘::’ before ‘(’ token|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp|43|error: expected identifier before ‘(’ token|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp|43|error: ‘scalar_add_op’ is not a member of ‘Eigen::internal’|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp|44|error: expected ‘(’ before ‘>’ token|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp|50|error: ‘scalar_add_op’ in namespace ‘Eigen::internal’ does not name a type|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp|50|error: expected template-argument before ‘<’ token|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp|50|error: expected ‘>’ before ‘<’ token|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp|52|error: wrong number of template arguments (1, should be 2)|
/usr/local/include/Eigen/src/Core/util/ForwardDeclarations.h|91|error: provided for ‘template<class UnaryOp, class MatrixType> class Eigen::CwiseUnaryOp’|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp|53|error: expected ‘::’ before ‘operator’|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp|53|error: expected identifier before ‘operator’|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp||In function ‘const int Eigen::operator+(const typename Eigen::internal::traits<T>::Scalar&, const Eigen::MatrixBase<Derived>&)’:|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp|56|error: ‘scalar_add_op’ in namespace ‘Eigen::internal’ does not name a type|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp|56|error: expected template-argument before ‘<’ token|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp|56|error: expected ‘>’ before ‘<’ token|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp|58|error: wrong number of template arguments (1, should be 2)|
/usr/local/include/Eigen/src/Core/util/ForwardDeclarations.h|91|error: provided for ‘template<class UnaryOp, class MatrixType> class Eigen::CwiseUnaryOp’|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp|58|error: expected ‘::’ before ‘(’ token|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp|58|error: expected identifier before ‘(’ token|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp|58|error: ‘scalar_add_op’ is not a member of ‘Eigen::internal’|
/usr/local/include/boost/numeric/odeint/external/eigen/eigen_algebra.hpp|59|error: expected ‘(’ before ‘>’ token|
||=== Build failed: 32 error(s), 0 warning(s) (0 minute(s), 7 second(s)) ===|
I also tried to include
boost/numeric/odeint/external/eigen/eigen.hpp
instead of eigen_algebra.hpp and received the same error messages when including eigen_algebra.hpp. It seems like Boost::odeint v1.65.1 is not compatible with Eigen v3.3.4. My question is if there is an (un)official header file that provides a support of Eigen 3.3.4 to Boost::odeint 1.65.1, or did I make something wrong during template specializations and/or operator overloading for the vector space algebra?
I also found a solution for "typecasting" std std::vector<> to Eigen::VectorXd
and vice versa, but I think that using std::vector as a state stype, and then internally "casting it" to Eigen::VectorXd, then "casting the result back" to std::vector<> would result in a lower performance than that of mentioned in the introduction since my vectors are huge and ten tousands or more accepted steps are required to perform an integration. I hope my question was accurate enough and the community can kindly help me solving my problem.