Generic Constexpr Lookup Table C++11 - c++

I'm trying to construct a generic lookup table that takes a generator function and creates the table at compile time.Here is the code for the table and generation:
#ifndef CONSTEXPR_LOOKUPTABLE_H
#define CONSTEXPR_LOOKUPTABLE_H
#include <cstddef>
/* Generate a range */
template <std::size_t... Is>
struct seq{};
template <std::size_t N, std::size_t... Is>
struct gen_seq : gen_seq<N - 1, N - 1, Is...>{};
template <std::size_t... Is>
struct gen_seq<0, Is...> : seq<Is...>{};
/*
The lookup table consisting of values to be
computed at compile-time
*/
template<std::size_t N, class T>
struct LookUpTable{
std::size_t indexes[N];
T values[N];
static constexpr std::size_t length = N;
};
/*
Generate the table from a generator function
*/
template <class Lambda, std::size_t... Is>
constexpr auto LookUpTableGenerator(seq<Is...>, Lambda f) ->
LookUpTable<sizeof...(Is), decltype(f(Is)...)>
{
return {{ Is... }, { f(Is)... }};
}
template <std::size_t N, class Lambda>
constexpr auto LookUpTableGenerator(Lambda f) ->
decltype(LookUpTableGenerator(gen_seq<N>{}, f))
{
return LookUpTableGenerator(gen_seq<N>{}, f);
}
#endif
Here is the main function:
#include <iostream>
#include <memory>
#include <vector>
#include <string>
#include "ConstExprLookupTable.h"
typedef unsigned short ushort;
typedef unsigned char byte;
/*
There are only 10 digits (0 - 9)
*/
static constexpr ushort DIGITS = 10;
/*
A table to prevent repeated division calculation:
table[i][j] = (i + j) / 10;
*/
static constexpr ushort carry_table[DIGITS][DIGITS] = \
{
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
{0, 0, 0, 0, 0, 0, 0, 1, 1, 1},
{0, 0, 0, 0, 0, 0, 1, 1, 1, 1},
{0, 0, 0, 0, 0, 1, 1, 1, 1, 1},
{0, 0, 0, 0, 1, 1, 1, 1, 1, 1},
{0, 0, 0, 1, 1, 1, 1, 1, 1, 1},
{0, 0, 1, 1, 1, 1, 1, 1, 1, 1},
{0, 1, 1, 1, 1, 1, 1, 1, 1, 1}
};
static constexpr double myFunc(double x)
{
return x / DIGITS;
}
int main()
{
constexpr std::size_t length = 100;
auto table = LookUpTableGenerator<length>(myFunc);
for (auto v : table.values){
std::cout << v << " ";
}
std::cout << "\n";
}
However, this generates the following compile-time errors:
ConstExprLookupTable.h:33:46: error: template argument 2 is invalid
LookUpTable<sizeof...(Is), decltype(f(Is)...)>
^
ConstExprLookupTable.h:33:46: error: template argument 2 is invalid
ConstExprLookupTable.h:33:46: error: template argument 2 is invalid
ConstExprLookupTable.h:33:46: error: template argument 2 is invalid
ConstExprLookupTable.h:33:46: error: template argument 2 is invalid
ConstExprLookupTable.h:33:46: error: template argument 2 is invalid
ConstExprLookupTable.h:33:46: error: template argument 2 is invalid
ConstExprLookupTable.h:33:46: error: template argument 2 is invalid
ConstExprLookupTable.h:33:46: error: template argument 2 is invalid
ConstExprLookupTable.h:33:1: error: invalid use of template-name ‘LookUpTable’ without an argument list
LookUpTable<sizeof...(Is), decltype(f(Is)...)>
^
ConstExprLookupTable.h:33:12: error: expected initializer before ‘<’ token
LookUpTable<sizeof...(Is), decltype(f(Is)...)>
^
virt.cpp: In function ‘int main()’:
virt.cpp:88:53: error: no matching function for call to ‘LookUpTableGenerator(double (&)(double))’
auto table = LookUpTableGenerator<length>(myFunc);
My questions are (finally!):
1) Is this possible to do? When I replace the class T parameter of the lookup table with a concrete type (like a double), the code compiles fine.
2) I think the error is here:
template <class Lambda, std::size_t... Is>
constexpr auto LookUpTableGenerator(seq<Is...>, Lambda f) ->
LookUpTable<sizeof...(Is), decltype(f(Is)...)>
{
return {{ Is... }, { f(Is)... }};
}
It seems to not like the decltype. What should the decltype be in this case?

There are lots of contexts where a pack can be expanded, but decltype isn't one of them. You'd have to just wrap your pack in some metafunction that pulls out the type. Something as easy as:
template <typename T, typename... >
using first = T;
And then use it:
template <class Lambda, std::size_t... Is>
constexpr auto LookUpTableGenerator(seq<Is...>, Lambda f) ->
LookUpTable<sizeof...(Is), first<decltype(f(Is))...>>
Though since all the Is are the same type anyway (size_t), you could just use that directly:
template <class Lambda, std::size_t... Is>
constexpr auto LookUpTableGenerator(seq<Is...>, Lambda f) ->
LookUpTable<sizeof...(Is), decltype(f(std::declval<size_t>()))>

Related

In C++, how do I create a constexpr aggregate initialization for a struct that has an array of structs in it?

I am working in C++ and I want to create an initializer list for a struct of array of structs and I keep getting the same compilation error.
Here is my struct:
typedef struct SetpointChange
{
uint8_t hours;
uint8_t minutes;
} SetpointChangeTime_t;
typedef struct SetpointChangesDaySchedule
{
SetpointChangeTime_t dayChanges[4];
} SetpointChangesDaySchedule_t;
typedef struct SetpointChangesWeekSchedule
{
SetpointChangeTime_t weekChanges[2];
} SetpointChangesWeekSchedule_t;
Here is my initializer list:
static constexpr SetpointChangesWeekSchedule defaultSchedule = {
{
{0, 0},
{0, 0},
{0, 0},
{0, 0}
},
{
{0, 0},
{0, 0},
{0, 0},
{0, 0}
}
};
I am getting this error:
error: too many initializers for 'SetpointProgram::SetpointChange_t [2]' {aka 'SetpointProgram::SetpointChange [2]'}
75 | };
| ^
My initialization syntax seems to be very correct... I don't understand why I am getting this error.
This is aggregate initialization, not initializer list. You need to double braces in some places:
#include <cstdint>
typedef struct SetpointChange
{
uint8_t hours;
uint8_t minutes;
} SetpointChangeTime_t;
typedef struct SetpointChangesDaySchedule
{
SetpointChangeTime_t dayChanges[4];
} SetpointChangesDaySchedule_t;
typedef struct SetpointChangesWeekSchedule
{
SetpointChangesDaySchedule_t weekChanges[2];
} SetpointChangesWeekSchedule_t;
static constexpr SetpointChangesWeekSchedule defaultSchedule = {{
{{
{0, 0},
{0, 0},
{0, 0},
{0, 0}
}},
{{
{0, 0},
{0, 0},
{0, 0},
{0, 0}
}}
}};
Explanation is: first braces are for object, second are for array inside object.
Compiler allows to use single set, like this:
struct Test
{
int a[5];
};
Test t = {1, 2, 3, 4, 5};
But in your case it will look like:
static constexpr SetpointChangesWeekSchedule defaultSchedule = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
Which is probably too confusing.

How to transform 2D tuple [x][y] to [y][x] and call variadic function for each result set

I want to "rotate" the axis of a 2D tuple and call a variadic function for each of the result sets.
All tuple elements have the same type, but the element items/attributes might have different type.
Starting from
constexpr auto someData = std::make_tuple(
std::make_tuple(1, 2, 3.0),
std::make_tuple(4, 5, 6.0),
std::make_tuple(7, 8, 9.0));
the result I want to achieve, are calls to a variadic function like this
someFunction(1, 4, 7);
someFunction(2, 5, 8);
someFunction(3.0, 6.0, 9.0);
I was trying to solve this using std::get<index>(tuple) in a lambda to create indices using std::make_index_sequence and invoke a variadic function, passing tuple elements via std::apply, like this (without success).
#include <iostream>
#include <tuple>
constexpr auto someFunction(auto&&... args) {
//do some stuff
((std::cout << args),...);
}
int main() {
constexpr auto someData = std::make_tuple(
std::make_tuple(1, 2, 3.0),
std::make_tuple(4, 5, 6.0),
std::make_tuple(7, 8, 9.0)
);
// want to get
// someFunction(1, 4, 7);
// someFunction(2, 5, 8);
// someFunction(3.0, 6.0, 9.0);
using t0_t = typename std::tuple_element<0, decltype(someData)>::type;
[] <std::size_t... I> (auto&& tuple, std::index_sequence<I...>) {
([&] (std::size_t i) {
std::apply([&](auto&&... args) {
//(std::get<i>(args), ...);
// someFunction ((std::get<i>(args), ...));
}, tuple);
}(I), ...);
}(std::forward<decltype(someData)>(someData),
std::make_index_sequence<std::tuple_size<t0_t>::value>{});
}
How can that be done correctly?
Use nested lambdas, one to expand the index and one to expand the tuple
constexpr auto someData = std::make_tuple(
std::make_tuple(1, 2, 3.0),
std::make_tuple(4, 5, 6.0),
std::make_tuple(7, 8, 9.0)
);
// someFunction(1, 4, 7);
// someFunction(2, 5, 8);
// someFunction(3.0, 6.0, 9.0);
std::apply([](auto first_tuple, auto... rest_tuples) {
[&]<std::size_t... I>(std::index_sequence<I...>) {
([]<size_t N>(auto... tuples) {
someFunction(std::get<N>(tuples)...);
}.template operator()<I>(first_tuple, rest_tuples...), ...);
}(std::make_index_sequence<std::tuple_size_v<decltype(first_tuple)>>{});
}, someData);
Demo

Create a new object inside a template constexpr function using two old objects

I wrote a template class that represents a Tensor(basically a Matrix)
and all its operations must be constexpr to be evaluated at compile time.
My main problem is, that an operation called contraction, creates a new Tensor C using parameters from other tensor objects.
This Tensor C combines the parameter packs of two other Tensors(A and B), but it removes one index from one tensor(A) and one index from the other tensor(B) before creation.
Is there any possibility to do this using constexpr functions?
The following code is my tensor class:
enum Index : int {lower = 0, upper = 1};
template<int Size, typename T>
struct Array{
T array[Size];
Array(const T * a){
for(int i = 0; i < Size; i++){
array[i] = a[i];
}
}
};
template<int base, int exponent>
int constexpr pow(){
if constexpr(exponent == 0){
return 1;
}else{
return base * pow<base, exponent-1>();
}
}
template<typename T = double, auto ...IndicesN>
class TensorND{
private:
const Array<pow<3, sizeof...(IndicesN)>(), T> matrix;
const Index _indices[sizeof...(IndicesN)] = {IndicesN...};
public:
constexpr TensorND(const T * arr): matrix(arr){}
constexpr TensorND(T * arr): matrix(arr){}
};
A function that takes the positions to remove the indices and it takes two tensors:
template<auto removeV1, auto removeV2, typename A, typename B>
constexpr auto contraction(const A tensor1, const B tensor2){
/*
*code for arr later
*/
return TensorND< >(arr);
}
A desired usecase:
int main () {
const double arr[27] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27};
const auto tensorA = new TensorND<double, upper, upper, upper>(arr);
const auto tensorB = new TensorND<double, lower, lower, upper>(arr);
//left "0" => remove the first upper from tensor1
//right "1" => remove the second lower from tensor2
//tensorC's parameter pack is now a combination of two parameter packs
//from left to right: upper(tensorA), upper(tensorA), lower(tensorB),upper(tensorB)
TensorND<double, upper, upper, lower, upper> tensorC = contraction<0, 1>(tensorA, tensorB);
//or
auto tensorC = contraction<0, 1>(tensorA, tensorB);
}

Write arbitrary Eigen object to row-major plain storage

I am writing a module to write data to a file which uses by convention only row-major storage. I would like my function to be able to allow both column-major and row-major Eigen objects as input.
Currently I first use Eigen to copy a column-major object to a row-major object, before I write. My code works well for most cases, but for Eigen::VectorXi compiling fails with an assertion that I don't understand. How do I solve this? Can I avoid creating many cases?
The code (writing is mimicked by outputting a std::vector):
#include <vector>
#include <iostream>
#include <Eigen/Eigen>
template <class T, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
std::vector<T> write(const Eigen::Matrix<T,Rows,Cols,Options,MaxRows,MaxCols>& matrix)
{
std::vector<T> data(static_cast<size_t>(matrix.size()));
if (matrix.IsRowMajor) {
std::copy(matrix.data(), matrix.data()+matrix.size(), data.begin());
return data;
} else {
Eigen::Matrix<T, Rows, Cols, Eigen::RowMajor, MaxRows, MaxCols> tmp = matrix;
return write(tmp);
}
}
int main()
{
Eigen::VectorXi matrix = Eigen::VectorXi::LinSpaced(10, 0, 9);
std::vector<int> output = write(matrix);
}
The compilation error:
In file included from test.cpp:3:
In file included from /usr/local/Cellar/eigen/3.3.7/include/eigen3/Eigen/Eigen:1:
In file included from /usr/local/Cellar/eigen/3.3.7/include/eigen3/Eigen/Dense:1:
In file included from /usr/local/Cellar/eigen/3.3.7/include/eigen3/Eigen/Core:457:
/usr/local/Cellar/eigen/3.3.7/include/eigen3/Eigen/src/Core/PlainObjectBase.h:903:7: error: static_assert failed "INVALID_MATRIX_TEMPLATE_PARAMETERS"
EIGEN_STATIC_ASSERT((EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, (Options&RowMajor)==RowMajor)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/local/Cellar/eigen/3.3.7/include/eigen3/Eigen/src/Core/util/StaticAssert.h:33:40: note: expanded from macro 'EIGEN_STATIC_ASSERT'
#define EIGEN_STATIC_ASSERT(X,MSG) static_assert(X,#MSG);
^ ~
/usr/local/Cellar/eigen/3.3.7/include/eigen3/Eigen/src/Core/PlainObjectBase.h:535:7: note: in instantiation of member function 'Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 1, -1, 1>
>::_check_template_params' requested here
_check_template_params();
^
/usr/local/Cellar/eigen/3.3.7/include/eigen3/Eigen/src/Core/Matrix.h:377:9: note: in instantiation of function template specialization 'Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 1, -1, 1>
>::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >' requested here
: Base(other.derived())
^
test.cpp:14:79: note: in instantiation of function template specialization 'Eigen::Matrix<int, -1, 1, 1, -1, 1>::Matrix<Eigen::Matrix<int, -1, 1, 0, -1, 1> >' requested here
Eigen::Matrix<T, Rows, Cols, Eigen::RowMajor, MaxRows, MaxCols> tmp = matrix;
^
test.cpp:23:31: note: in instantiation of function template specialization 'write<int, -1, 1, 0, -1, 1>' requested here
std::vector<int> output = write(matrix);
^
1 error generated.
Understanding the static assertion
Unfortunately the assertion is really not self-explanatory and the only thing you can get from it is the hint, that something is wrong with your template parameters. If we look into Eigen's source code we find the following beginning on line 903:
EIGEN_STATIC_ASSERT((EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, (Options&RowMajor)==RowMajor)
&& EIGEN_IMPLIES(MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1, (Options&RowMajor)==0)
&& ((RowsAtCompileTime == Dynamic) || (RowsAtCompileTime >= 0))
&& ((ColsAtCompileTime == Dynamic) || (ColsAtCompileTime >= 0))
&& ((MaxRowsAtCompileTime == Dynamic) || (MaxRowsAtCompileTime >= 0))
&& ((MaxColsAtCompileTime == Dynamic) || (MaxColsAtCompileTime >= 0))
&& (MaxRowsAtCompileTime == RowsAtCompileTime || RowsAtCompileTime==Dynamic)
&& (MaxColsAtCompileTime == ColsAtCompileTime || ColsAtCompileTime==Dynamic)
&& (Options & (DontAlign|RowMajor)) == Options),
INVALID_MATRIX_TEMPLATE_PARAMETERS)
Even though the compiler indicates that
EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, (Options&RowMajor)==RowMajor)
causes the error, the following line really does:
EIGEN_IMPLIES(MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1, (Options&RowMajor)==0)
Understanding what triggers the assertion
You provide Eigen::VectorXi as an input for write. Eigen::VectorXi is really just a typedef for
Eigen::Matrix<int, Eigen::Dynamic, 1, Eigen::ColMajor, Eigen::Dynamic, 1>
Therefore the line
Eigen::Matrix<T, Rows, Cols, Eigen::RowMajor, MaxRows, MaxCols> tmp = matrix;
in write expands to
Eigen::Matrix<int, Eigen::Dynamic, 1, Eigen::RowMajor, Eigen::Dynamic, 1> tmp = matrix;
which triggers the assertion, since a matrix with MaxColsAtCompileTime==1 and MaxRowsAtCompileTime!=1 must not be RowMajor.
Solve your problem
The problem now is that even though you can check if your input matrix is a vector, row-major or column-major, you cannot declare
Eigen::Matrix<T, Rows, Cols, Eigen::RowMajor, MaxRows, MaxCols>
if it is no legal to do so at compile-time (and it isn't due to the static assertion).
You have the following options to make your code work:
1. if constexpr (C++17)
C++17 offers a way for detecting at compile-time if a certain conditional branch will be taken or not. The downside of this approach (beside the requirement for a C++17 compiler) is that you can only test for constant expressions.
In the concrete example this looks like this:
template <class T, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
std::vector<T> write(const Eigen::Matrix<T, Rows, Cols, Options, MaxRows, MaxCols>& matrix)
{
typedef Eigen::Matrix<T, Rows, Cols, Options, MaxRows, MaxCols> MatrixType;
std::vector<T> data(static_cast<size_t>(matrix.size()));
if constexpr (MatrixType::MaxRowsAtCompileTime == 1 ||
MatrixType::MaxColsAtCompileTime ==1 ||
(MatrixType::Options&Eigen::RowMajor) == Eigen::RowMajor) {
std::copy(matrix.data(), matrix.data() + matrix.size(), data.begin());
return data;
} else {
Eigen::Matrix<T, Rows, Cols, Eigen::RowMajor, MaxRows, MaxCols> tmp = matrix;
return write(tmp);
}
}
2. SFINAE
You can dispatch the call to write at compile-time using SFINAE by using std::enable_if. The following example uses a slightly modified version of your original code but everything should be clear from context:
// matrix is either a vector or in row-major
template <typename Derived>
std::vector<typename Derived::Scalar> write(const Eigen::MatrixBase<Derived>& matrix,
typename std::enable_if<Derived::MaxRowsAtCompileTime == 1 ||
Derived::MaxColsAtCompileTime == 1 ||
(Derived::Options & Eigen::RowMajor) == Eigen::RowMajor,
Derived>::type* = 0)
{
std::vector<typename Derived::Scalar> data(
static_cast<size_t>(matrix.size()));
std::copy(matrix.derived().data(), matrix.derived().data() + matrix.size(),
data.begin());
return data;
}
// matrix is neither a vector nor in row-major
template <typename Derived>
std::vector<typename Derived::Scalar> write(const Eigen::MatrixBase<Derived>& matrix,
typename std::enable_if<Derived::MaxRowsAtCompileTime != 1 &&
Derived::MaxColsAtCompileTime != 1 &&
(Derived::Options & Eigen::RowMajor) == 0,
Derived>::type* = 0)
{
Eigen::Matrix<typename Derived::Scalar, Derived::RowsAtCompileTime,
Derived::ColsAtCompileTime, Eigen::RowMajor,
Derived::MaxRowsAtCompileTime, Derived::MaxColsAtCompileTime> tmp = matrix;
return write(tmp);
}
This works using a C++11 compiler.
Other options would be to specialise the template but it will get even more lengthy than the SFINAE approach.
Some test cases:
Eigen::Matrix<int, 3, 3, Eigen::RowMajor> m;
m << 1, 2, 3,
1, 2, 3,
1, 2, 3;
std::vector<int> output = write(m);
for (const auto& element : output) {
std::cout << element << " ";
}
Output: 1 2 3 1 2 3 1 2 3
Eigen::Matrix<int, 3, 3, Eigen::ColMajor> m;
m << 1, 2, 3,
1, 2, 3,
1, 2, 3;
std::vector<int> output = write(m);
for (const auto& element : output) {
std::cout << element << " ";
}
Output: 1 2 3 1 2 3 1 2 3
Eigen::VectorXi m = Eigen::VectorXi::LinSpaced(10, 0, 9);
std::vector<int> output = write(m);
for (const auto& element : output) {
std::cout << element << " ";
}
Output: 0 1 2 3 4 5 6 7 8 9
Eigen::RowVectorXi m = Eigen::RowVectorXi::LinSpaced(10, 0, 9);
std::vector<int> output = write(m);
for (const auto& element : output) {
std::cout << element << " ";
}
Output: 0 1 2 3 4 5 6 7 8 9
A simpler solution is to let Eigen::Ref does all the job for you:
Ref<const Matrix<T,Rows,Cols,Cols==1?ColMajor:RowMajor,MaxRows,MaxCols>,0, InnerStride<1> > row_maj(matrix);
Then row_maj will be guaranteed to be sequentially stored in row-major order. If matrix is compatible, then no copy occurs. No branch, no SFINAE, etc.
Here matrix can be any expression, not only a Matrix<...> but also sub-matrices, Map, another Ref, etc.
To handle any expressions, just replace Rows and the likes with XprType::RowsAtCompileTime where XprType is the type of matrix.
template <class XprType>
std::vector<typename XprType::Scalar> write(const Eigen::MatrixBase<XprType>& matrix)
{...}

Eigen matrix ros/cols not working out right

I can't get this to compile:
Eigen::Map<Eigen::Matrix<const T, EA::ColsAtCompileTime, 1>> x(vec);
auto result = a_ * x - b_; // a(60r,1200c) * x(1200r,1c) - b(60r,1c)
The two errors (about 1000 lines each) eventually conclude that the * and - operators can't be "overloaded" (their term, not mine).
a_ is of this type: typedef Eigen::Map<Eigen::Matrix<double, ROWS, COLS>> EA;
b_ is of this type: typedef Eigen::Map<Eigen::Matrix<double, ROWS, 1>> EB;
T is the Ceres Solver Jet type. The errors seem to bespeak a column/row mismatch rather than a type problem. I could be wrong, though; the output is entirely too verbose. Did I misunderstand how the rows and columns work with Eigen matrix operators?
Update: I followed the "fatal-errors" suggestion:
In file included from /usr/include/eigen3/Eigen/Core:437:0,
from /usr/local/include/ceres/jet.h:165,
from /usr/local/include/ceres/internal/autodiff.h:145,
from /usr/local/include/ceres/autodiff_cost_function.h:132,
from /usr/local/include/ceres/ceres.h:37,
from /home/brannon/Workspace/Solver/music_solver.cpp:3:
/usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h: In instantiation of ‘class Eigen::PlainObjectBase<Eigen::Matrix<const double, 1200, 1, 0, 1200, 1> >’:
/usr/include/eigen3/Eigen/src/Core/Matrix.h:178:7: required from ‘class Eigen::Matrix<const double, 1200, 1, 0, 1200, 1>’
/usr/include/eigen3/Eigen/src/Core/Map.h:24:32: required from ‘struct Eigen::internal::traits<Eigen::Map<Eigen::Matrix<const double, 1200, 1, 0, 1200, 1>, 0, Eigen::Stride<0, 0> > >’
/usr/include/eigen3/Eigen/src/Core/util/ForwardDeclarations.h:32:54: required from ‘struct Eigen::internal::accessors_level<Eigen::Map<Eigen::Matrix<const double, 1200, 1, 0, 1200, 1>, 0, Eigen::Stride<0, 0> > >’
/usr/include/eigen3/Eigen/src/Core/util/ForwardDeclarations.h:113:75: required from ‘class Eigen::Map<Eigen::Matrix<const double, 1200, 1, 0, 1200, 1>, 0, Eigen::Stride<0, 0> >’
/home/brannon/Workspace/Solver/music_solver.cpp:18:72: required from ‘bool MusicCostFunctor<MATRIX_A, MATRIX_B>::operator()(const T*, T*) const [with T = double; MATRIX_A = Eigen::Map<Eigen::Matrix<double, 60, 1200, 0, 60, 1200>, 0, Eigen::Stride<0, 0> >; MATRIX_B = Eigen::Map<Eigen::Matrix<double, 60, 1, 0, 60, 1>, 0, Eigen::Stride<0, 0> >]’
/usr/local/include/ceres/internal/variadic_evaluate.h:175:19: required from ‘static bool ceres::internal::VariadicEvaluate<Functor, T, N0, 0, 0, 0, 0, 0, 0, 0, 0, 0>::Call(const Functor&, const T* const*, T*) [with Functor = MusicCostFunctor<Eigen::Map<Eigen::Matrix<double, 60, 1200, 0, 60, 1200>, 0, Eigen::Stride<0, 0> >, Eigen::Map<Eigen::Matrix<double, 60, 1, 0, 60, 1>, 0, Eigen::Stride<0, 0> > >; T = double; int N0 = 1200]’
/usr/local/include/ceres/autodiff_cost_function.h:208:17: required from ‘bool ceres::AutoDiffCostFunction<CostFunctor, kNumResiduals, N0, N1, N2, N3, N4, N5, N6, N7, N8, N9>::Evaluate(const double* const*, double*, double**) const [with CostFunctor = MusicCostFunctor<Eigen::Map<Eigen::Matrix<double, 60, 1200, 0, 60, 1200>, 0, Eigen::Stride<0, 0> >, Eigen::Map<Eigen::Matrix<double, 60, 1, 0, 60, 1>, 0, Eigen::Stride<0, 0> > >; int kNumResiduals = 1; int N0 = 1200; int N1 = 0; int N2 = 0; int N3 = 0; int N4 = 0; int N5 = 0; int N6 = 0; int N7 = 0; int N8 = 0; int N9 = 0]’
/home/brannon/Workspace/Solver/music_solver.cpp:115:1: required from here
/usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h:585:27: error: ‘static Eigen::PlainObjectBase<Derived>::MapType Eigen::PlainObjectBase<Derived>::Map(Eigen::PlainObjectBase<Derived>::Scalar*) [with Derived = Eigen::Matrix<const double, 1200, 1, 0, 1200, 1>; Eigen::PlainObjectBase<Derived>::MapType = Eigen::Map<Eigen::Matrix<const double, 1200, 1, 0, 1200, 1>, 0, Eigen::Stride<0, 0> >; Eigen::PlainObjectBase<Derived>::Scalar = const double]’ cannot be overloaded
static inline MapType Map(Scalar* data)
^~~
You need to tell Eigen how to mix your scalar types through Eigen:: ScalarBinaryOpTraits. See similar questions with solutions there:
https://forum.kde.org/viewtopic.php?f=74&t=141467
Transform matrix of 3D positions with corresponding transformation matrix
After looking again at this example:
https://groups.google.com/d/msg/ceres-solver/7ZH21XX6HWU/Z3E-k2fbAwAJ
I realized that I put the const in the wrong spot. It's supposed to be Map<const... rather than <const T.