Compile error on boost::multi_array builder - c++

It is said that we'd better use a multi_array builder if we want to use the multi_array more efficiently. However, I'm so new to both template and boost, I tried to copy some code from a book. It looks like this:
class multi_builder : boost::noncopyable
{
public:
typedef boost::multi_array<T,N> array_type;
typedef boost::shared_ptr<array_type > type;
private:
boost::any ext;
public:
multi_builder() : ext(boost::extents){}
~multi_builder(){}
template<std::size_t n>
void dim(std::size_t x)
{
BOOST_STATIC_ASSERT(n >= 0 && n < N);
ext = boost::any_cast<boost::detail::multi_array::extent_gen<n> >(ext) [x];
}
boost::type create(void)
{
return boost::type<array_type>(new array_type(boost::any_cast<boost::detail::multi_array::extent_gen<N> >(ext)));
}
};
However, when I tried to use it in the code like this:
multi_builder<int,2> builder;
builder.dim<0>(2);
builder.dim<1>(2);
BOOST_AUTO(mp,builder.create());
for(int i = 0,v = 0; i < 2; ++i)
for(int j = 0; j < 2; ++j)
(*mp)[i][j] = v++;
the compiler generates the following errors:
error:invalid use of template-name 'boost::type' without an argument list
error:'class multi_builder<int, 2u>' has no member named 'create'.
error:invalid type in declaration before '=' token
error:'class multi_builder<int, 2u>' has no member named 'create'
error:invalid type argument of 'unary *'
Could someone tell me how to fix the errors?

From the looks of it, the return type of create() lacks a template argument list. I haven't used this Boost component but based on how the value is returned it should probably look like this:
boost::type<array_type> create(void)

There are several problem with the code.
First you are probably missing template parameters for the class (as the other answer pointed out).
Second, create seems to return a smart pointer (shared_ptr) that you define as type in your class (bad name by the away).
This code now compiles and runs: https://godbolt.org/z/qs19eYfso
#include<boost/any.hpp>
#include<boost/multi_array.hpp>
#include<boost/shared_ptr.hpp>
template<class T, std::size_t N>
class multi_builder : boost::noncopyable
{
public:
typedef boost::multi_array<T,N> array_type;
typedef boost::shared_ptr<array_type > type;
private:
boost::any ext;
public:
multi_builder() : ext(boost::extents){}
~multi_builder(){}
template<std::size_t n>
void dim(std::size_t x)
{
BOOST_STATIC_ASSERT(n >= 0 && n < N);
ext = boost::any_cast<boost::detail::multi_array::extent_gen<n> >(ext) [x];
}
type create(void)
{
return type(new array_type(boost::any_cast<boost::detail::multi_array::extent_gen<N> >(ext)));
}
};
int main() {
multi_builder<int,2> builder;
builder.dim<0>(2);
builder.dim<1>(2);
auto mp = builder.create();
for(int i = 0,v = 0; i < 2; ++i)
for(int j = 0; j < 2; ++j)
(*mp)[i][j] = v++;
}

Related

Templated elipsis constructor C++

I want to create a templated math vector class. But it says code editor says ambiguous constructor.
I use only header file!!
.h
template<class T>
class MathVec {
private:
std::vector<T> mathVec;
size_t dimension;
public:
MathVec(size_t dim);
MathVec(size_t dim, ...);
MathVec(const MathVec& other);
MathVec();
void print();
};
template<class T>
MathVec<T>::MathVec(size_t dim) {
this->dimension = dim;
this->mathVec = std::vector<T>(dim,0);
}
template<class T>
MathVec<T>::MathVec(size_t dim, ...) {
this->mathVec = std::vector<T>(dim);
this->dimension = dim;
va_list list;
va_start(list, dim);
for (size_t i = 0; i < dim; i++){
this->mathVec[i] = va_arg(list, T);
}
va_end(list);
}
template<class T>
MathVec<T>::MathVec(const MathVec & other) {
this->dimension = other.dimension;
this->mathVec = other.mathVec;
}
template<class T>
MathVec<T>::MathVec() {
this->dimension = 0;
}
template<class T>
void MathVec<T>::print() {
for(int i = 0; i < this->dimension; ++i)
std::cout << this->mathVec[i] << " ";
std::cout << std::endl;
}
In the main.cpp file I use the following code it is working.
MathVec<int> vect(3,1,2,3);
vect.print();
But if I use the following code it is not working
MathVec<int> vect(1);
vect.print();
The error message is the following.
main.cpp:9:18: error: call to constructor of 'MathVec<int>' is ambiguous
mathvec.h:14:9: note: candidate constructor
mathvec.h:15:9: note: candidate constructor
mathvec.h:16:9: note: candidate constructor
I assume that wrong with the ellipsis, but I do not know what can be the problem, and how to solve this issue.
Modern C++ has better way to accomplish that. Create the following constructor:
MathVec( std::initializer_list<T> values )
Usage:
MathVec<int> vect( { 1, 2, 3 } );
My guess would be that the compiler does not know what constructor to call, as these two:
MathVec(size_t dim);
MathVec(size_t dim, ...);
can both be called by
MathVec<int> vect(1);
may I offer some improvements to your design?
There is no reason to pass dimension as a parameter to constructor. I think be better to make it template parameter.
Thus, when you try mix in some expression matrices with different dimensions, you catch error at compile time, not when program executes ;)
Working example:
#include <vector>
#include <iostream>
template <typename T, unsigned int dim>
class Matrix
{
const unsigned int m_dim = dim;
std::vector<T> m_vec;
public:
Matrix(): m_vec(std::vector<T>(m_dim, 0)) {}
virtual ~Matrix() {}
//suppose, we want m_vec be R/O for public
const std::vector<T>& Read() {return m_vec;}
};
int main(int, char **)
{
Matrix<double, 4> m;
for (auto& x : m.Read())
std::cout << x << std::endl;
}
In general I would avoid using C style variadic arguments, check variadic templates instead (C++11) or fold expressions (C++17)

Pass by reference if possible, by value otherwise

I would like to create an instance of my class Matrix using a transformation on another matrix in a template function.
Matrix<T> m(A.tri_lo());
The transformation, here tri_lo() returns a new value, so here my code throws an error :
error C2662: 'Matrix<long double> Matrix<long double>::tri_lo(bool)' : cannot convert a 'this' pointer from 'const Matrix<long double>' to 'Matrix<long double> &'
I tried overloading the constructor for pass-by-value but I couldn't get it to work. Here are my constructors :
Matrix() : data{ {T{}} } {}; // Implemented
Matrix(std::vector<std::vector<T>> _data) : data{ _data } {}; // Implemented
Matrix(unsigned int const lines, unsigned int const cols) { // Implemented
for (unsigned int i = 0; i < lines; i++) { this->data.push_back(std::vector<T>(cols, T())); }
};
template<class T2> Matrix(Matrix<T2> const& other) : data{ other.data } {}; // Implemented
template<class T2> Matrix(Matrix<T2> const other) : data{ other.data } {} // Implemented
Where am I going wrong ?
EDIT : here is the context.
template<class T>
template<class T2>
auto Matrix<T>::operator-(Matrix<T2> const& other) {
assert(this->lines() == other.lines());
assert(this->cols() == other.cols());
decltype(std::declval<T>() - std::declval<T2>()) T3;
Matrix<T3> res(this->lines(), this->cols());
for (unsigned int const i = 0; i < this->lines(); i++) {
for (unsigned int const j = 0; j < this->cols(); i++) {
res[i][j] -= other[i][j];
}
}
return res;
}
Here is the full pastebin. Feel free to include a small code review if needed !
Main issues
There are a lot of issues with your code that Visual Studio didn't catch, but that still break the code.
For example, on lines 86 and 87 of your pastebin file:
decltype (std::declval<T>()*std::declval<T2>()) T3;
Matrix<T3> result = Matrix<T3>::gen_full(this->lines(), other.cols());
You declare a variable called T3, and then try to use it as a template parameter for Matrix. What it should be is:
// Declare T3 as a type
using T3 = decltype (std::declval<T>()*std::declval<T2>());
// Now we can use T3
Matrix<T3> result = Matrix<T3>::gen_full(this->lines(), other.cols());
Or here, in gen_full:
template<class T>
Matrix<T> Matrix<T>::gen_full(unsigned int lines, unsigned int cols, T value){
for(unsigned int i = 0; i < lines; i++) {
std::vector<T> line;
for(unsigned int j = 0; j < cols; j++) {
line.push_back(value);
}
this->data.push_back(line); // Error here
}
};
You're using this, but gen_full is a static function so this isn't available.
We can rewrite it as:
template<class T>
Matrix<T> Matrix<T>::gen_full(unsigned int lines, unsigned int cols, T value){
Matrix<T> m;
for(unsigned int i = 0; i < lines; i++) {
std::vector<T> line;
for(unsigned int j = 0; j < cols; j++) {
line.push_back(value);
}
m.data.push_back(line); // Error here
}
return m;
};
You have the same issue on lines 346 and 348 that you had on 86 and 87:
decltype(std::declval<T>() - std::declval<T2>()) T3;
Matrix<T3> res(this->lines(), this->cols());
We can fix it the same way we did there (with using T3 = decltype(...))
On line 350, you declare i as const, and then you increment it. We can just remove the const and it works.
Other issues
Once we got through the main issues, there are still a few other issues that we can only catch by trying to instantiate the class.
For example, we can use a dummy function to get the compiler to check this for us:
void foo() {
// Forces the compiler to instantiate Matrix<double>
Matrix<double> A;
Matrix<double> B(A.tri_lo());
}
When we try to do this, we get a few cryptic errors, such as here on line 260:
Matrix<T> res(this->lines(), this->cols());
Gcc gives me the error
<source>: In instantiation of 'Matrix<T> Matrix<T>::tri_lo(bool) const [with T = double]':
<source>:365:31: required from here
<source>:262:15: error: passing 'const Matrix<double>' as 'this' argument discards qualifiers [-fpermissive]
262 | Matrix<T> res(this->lines(), this->cols());
| ^~~
What this means is that you're trying to use functions that aren't const (such as lines() and cols()) in a const context (since tri_lo is const)
We can fix this by marking lines() and cols() as const:
// On line 32 and 33
unsigned int cols() const; // Implemented
unsigned int lines() const; // Implemented
And here as well:
// Lines 71 to 75
template<class T>
unsigned int Matrix<T>::cols() const { return this->data.size(); };
template<class T>
unsigned int Matrix<T>::lines() const { return this->data[0].size(); };
What was causing the original problem?
As far as I can tell, the original problem occurred because lines() and cols() weren't marked const.
Conclusion
There were a lot of errors that Visual Studio didn't catch. It's a good idea to use a separate compiler, like gcc or clang, which will catch errors sooner and faster. You can use them online at https://godbolt.org, or you can install them locally.
Here is the original version of your code, along with the errors shown by gcc: https://godbolt.org/z/5eiRNw
And here's the updated version of your code, with the errors fixed (including the one described in your original post): https://godbolt.org/z/vFlyvk
You still need to add an implementation of Matrix<T>::gen_uninitialized, and on line 226, clang warns you that std::vector<T> diag(); is interpreted as the forward-declaration of a function named diag (remove the parenthesis), but everything else looks good!

Member function of derived class does not care about template argument

I want to simulate a chain of particles either in the up position or the down position. To this end I made a class that inherits from bitset. It looks like:
#include <bitset>
using namespace std;
template <size_t N>
class State : public bitset<N> {
public:
State<N>();
State<N>(size_t b);
long int E();
private:
size_t length;
};
template<unsigned long N>
State<N>::State()
: std::bitset<N>(), length(N)
{}
template<unsigned long N>
State<N>::State(size_t b)
: std::bitset<N>(b), length(N)
{}
Once such an object is instantiated using a certain length, I would like to find the energy associated to such an object. I want to do this
#include "state.h"
long int State::E(){
long int e = 0;
for (size_t i = 1; i != length; ++i)
e += (test[i] == test[i - 1]) ? 1 : -1;
return e;
}
I receive the error
state/state.cc:3:10: error: ‘template<long unsigned int N> class State’ used without template parameters
long int State::E(){
^~~~~
state/state.cc: In function ‘long int E()’:
state/state.cc:5:27: error: ‘length’ was not declared in this scope
for (size_t i = 1; i != length; ++i)
^~~~~~
state/state.cc:6:11: error: ‘test’ was not declared in this scope
e += (test[i] == test[i - 1]) ? 1 : -1;
^~~~
I understand this to mean that the compiler does not recognize that E() is a member function of my class due to a missing template argument. However, I was hoping there is a way that I can call s.E() on a State<20> object for instance. So once the object is instantiated I would like to be able to call E() without having to again specify the size. Is this possible? Thanks in advance!
There are two issues here: defining the member function E() of the class template State<N>, and accessing the test() member function of the dependent base class bitset<N>.
template<size_t N>
long int State<N>::E(){
long int e = 0;
for (size_t i = 1; i != length; ++i)
e += (this->test(i) == this->test(i - 1)) ? 1 : -1;
}
Note both the template<size_t N> and the State<N> as well as the this-> in front of test. See this Q&A for a detailed explanation.
Final note: also be careful: it's test() (parentheses) and operator[] (brackets) in std::bitset.
In the definition of member function of tempalte class, you must specify the template parameters as you did for the constructor.
The error "lenght not declared" should be fixed also by this change.
template <size_t N>
long int State<N>::E(){
long int e = 0;
for (size_t i = 1; i != length; ++i)
e += (test(i) == test(i - 1)) ? 1 : -1;
return e;
}

How to make types for indexing

I have something like:
Array definition:
array<array<Value, N_FOO_PER_BAR>, N_BAR> arr;
Access function:
Value getFoo(int barIdx, int fooIdx){
return arr[barIdx][fooIdx];
}
For-loop:
for(int i = 0; i < N_BAR; i ++){
for(int j = 0; j < N_FOO_PER_BAR; j ++){
arr[i][j].doSomething();
}
}
Problem: Indices for foo and bar can easily get mixed up when using getFoo(...).
I would like to define a type BarIdx and FooIdx and then the compiler should complain when I mix them up.
The access function would then look like:
function getFoo(BadIdx barIdx, FooIdx fooIdx){
return arr[barIdx][fooIdx];
}
The for-loop could look like:
for(BarIdx i = 0; i < N_BAR; i ++){
for(FooIdx j = 0; j < N_FOO_PER_BAR; j ++){
arr[i][j].doSomething();
}
}
So I'm looking how to define a type which (a) will issue a warning/error when used at the wrong place but (b) still behaves as much as an integer as possible, for for loop and array access with []. This should also work on CUDA, so I would prefer to use simple language constructs rather than a perfect solution.
The difficulty with doing this is that you can't simply inherit from int in C++, so you need to provide a wrapper which not only implicitly converts to and from int, but also provides all the necessary operators so that you can do things like:
BarIdx a = 0;
++a;
You might want to start with something simple like this:
template <typename T>
class IntegralWrapper {
T value;
public:
typedef T value_type;
IntegralWrapper() :value() {}
IntegralWrapper(T v) :value(v) {}
operator T() const { return value; }
};
Then add any operators you need later. You would then define your index classes like this:
class BarIdx : public IntegralWrapper<int> {};
class FooIdx : public IntegralWrapper<int> {};
Alternatively, here is a seemingly pretty complete integral wrapper solution taken from this question which you could probably use.
It will not trivial. The problems is not in defining the type for index, but that the operator [] of the array take size_type (std::size_t) which will reduce to null all your effort to differenciate the indexes.
I will suggest another kind of sintactic sugar:
struct Idx {int bar, foo;};
Access function:
Value& getValue(Idx i){
return arr[i.bar][i.foo];
}
For-loop:
for(Idx i{0,0} ; i.bar < N_BAR; i.bar ++){
for(i.foo = 0; i.foo < N_FOO_PER_BAR; i.foo ++){
getValue(i).doSomething();
}
}
but also:
for(auto &foos : arr){
for(auto &foo : foos){
foo.doSomething();
}
}

Pointer to array Maintain counter of elements

I have an interface which multiple classes inheritance.
class someInterface
{
virtual void someMethod() = 0;
}
class A : public someInterface
{
public:
void someMethod()
{
//Do something
}
}
class B : public someInterface
{
public:
void someMethod()
{
//Do something
}
}
class C : public someInterface
{
public:
void someMethod()
{
//Do something
}
}
For each of the classes A, B, C i have created an array with different sizes of their actual type inside a container class.
class AContainer
{
public:
A As[10];
}
class BContainer
{
public:
B Bs[5];
}
etc...
Furthermore i have an array of pointers to "SomeInterface", where i want to have a pointer to each of the actual arrays like this.
#define SOMEINTERRFACE_SIZE 3
someInterface *array[SOMEINTERRFACE_SIZE];
array[0] = AContainer.As; //Could also just be &AContainer.As[0]
array[1] = BContainer.Bs;
array[2] = CContainer.Cs;
for (int i = 0; i < SOMEINTERRFACE_SIZE; ++i)
{
int elements = //Here i need a solution to get the size
//So i can iterate through the array, which the pointer points to.
for (int i = 0; i < elements; ++i)
{
//Call the interface method on each element.
}
}
The problem occurs, when i have to use the someInterface array, since it isn't possible to get the size of the actual array through the someInterface pointer..
What is a good solution to this problem? I really need some help to solve this.
Also don't want to use dynamic allocation, so no solution with vector<> or malloc etc. because I'm writing to an Arduino.
It won't work. In C++ you have to know the size of the elements in an array. A, B, and C might be different sizes, so you can't treat arrays of them the same.
&AContainer.As[i] == &AContainer.As + i * sizeof(A)
but
&BContainer.Bs[i] == &BContainer.Bs + i * sizeof(B)
So it's impossible for the same machine code to iterate over arrays of A and of B. If you want to iterate over an array of objects, you need to know the exact type.
Remember in C++, if you want to get a polymorphic virtual call, you need to go through pointer or reference. The solution is to copy pointers to the elements in each array into one "master" array.
SomeInterface *ptrs[NUM_A + NUM_B + NUM_C];
SomeInterface **dest = ptrs;
for (int i = 0; i < NUM_A; ++i) {
*dest++ = &AContainer.As[i];
}
for (int i = 0; i < NUM_B; ++i) {
*dest++ = &BContainer.Bs[i];
}
// et cetera...
This only uses a little bit of extra space because you're storing pointers, not actual objects.
EDIT: I guess you could do something like this if you really want to save the space:
someInterface *arrays[] = { AContainer.As, BContainer.Bs, CContainer.Cs };
int objSizes[] = { sizeof(A), sizeof(B), sizeof(C) };
int arrLengths[] = { NUM_A, NUM_B, NUM_C };
for (int j = 0; j < sizeof(arrays)/sizeof(arrays[0]); ++j)
{
void *ptr = arrays[j];
for (int i = 0; i < arrLengths[j]; ++i) {
someInterface *iptr = (someInterface *)ptr;
iptr->method();
ptr += objSizes[j];
}
}
(this is untested, you might need to tweak a little.)
In theory since all those arrays are full of compile-time constants, it should optimize out to something fast. If it doesn't, the code will run slower because it will be incrementing pointers by a value only known at runtime instead of compile time. You should check the assembly output if you really care about speed.
Difficult to answer without knowing more details of your application - but here a a few ideas that might help.
Given:
class someInterface { public: virtual char someMethod() = 0; };
class A : public someInterface { public: char someMethod() { return 'A'; } };
class B : public someInterface { public: char someMethod() { return 'B'; } };
class C : public someInterface { public: char someMethod() { return 'C'; } };
You could hand-roll something like this:
class Array {
public:
void forEach( void(*function)(someInterface&) ) {
for (size_t i = 0 ; i < countA ; ++i) function(As[i]);
for (size_t i = 0 ; i < countB ; ++i) function(Bs[i]);
for (size_t i = 0 ; i < countC ; ++i) function(Cs[i]);
}
private:
enum {countA = 10, countB = 5, countC = 3};
A As[countA];
B Bs[countB];
C Cs[countC];
};
void doSomeMethod(someInterface& element) {
std::cout << element.someMethod();
}
int main(int, char**) {
Array array;
array.forEach(doSomeMethod);
return 0;
}
Note that by using the "callback" function doSomeMethod, we get around a typical problem of dispatching in polymorphic collections.
Of course, you don't want to keep hand-rolling things like that. Fortuanately the Arduino C++ compiler I checked out has template support, so you could do something like:
template <class T, size_t _size, class NextArray = void>
struct Array {
public:
typedef T value_type;
enum {size = _size};
void forEach( void(*function)(someInterface&) ) {
for (size_t i = 0 ; i < _size ; ++i)
function(elements[i]);
nextArray.forEach(function);
}
private:
T elements[_size];
NextArray nextArray;
};
template <class T, size_t _size>
struct Array<T, _size, void> {
public:
typedef T value_type;
enum {size = _size};
void forEach( void(*function)(someInterface&) ) {
for (size_t i = 0 ; i < _size ; ++i)
function(elements[i]);
}
private:
T elements[_size];
};
void doSomeMethod(someInterface& element) {
std::cout << element.someMethod();
}
int main(int, char**) {
Array<A, 10, Array<B, 5, Array<C, 3> > > array;
array.forEach(doSomeMethod);
return 0;
}
Which gets the compiler to write it for you for different combinations of types and sizes. A few things worth noting:
All the magic is done at compile time. Check out the assembly generated by an optimising compiler to see how small and fast this can be.
Read up on c++ "functors" if your callback function needs some state.
If your compiler supports variadic templates and/or lambdas, this becomes simpler (I'm assuming the Arduido compiler doesn't yet)
If you can't use the callback approach (and your compiler doesn't support lambdas yet), then you could try this next option, which incurs some small run-time cost over the option given above:
template <class Interface>
class ArrayInterface {
public:
virtual size_t getSize() = 0;
virtual Interface& getElement(size_t index) = 0;
};
template <class T, class Interface, size_t size>
class Array : public ArrayInterface<Interface> {
public:
size_t getSize() { return size; }
Interface& getElement(size_t index) { return element[index]; }
private:
T element[size];
};
int main(int, char**) {
Array<A, SomeInterface, 10> As;
Array<B, SomeInterface, 5> Bs;
Array<C, SomeInterface, 3> Cs;
const int SOMEINTERRFACE_SIZE = 3;
ArrayInterface<SomeInterface>* array[SOMEINTERRFACE_SIZE] = {&As, &Bs, &Cs};
for (size_t i = 0 ; i < SOMEINTERRFACE_SIZE ; ++i) {
ArrayInterface<SomeInterface>& innerArray = *array[i];
for (size_t j = 0 ; j < innerArray.getSize() ; ++j)
std::cout << innerArray.getElement(j).someMethod();
}
return 0;
}
(This last one uses an outer array of pointers, as per your question)
This post is already too long, so I haven't gone into much detail, or delved into options such as a single, flat array of member function pointers. If you have any questions, just shout.
Is it what you are trying to achive?
Iterate over a list of objects and call a reimplemented method of a common interface?
Put this piece of code anywhere in global C++ scope for testing.
#include <vector>
#include <iostream>
int TestSomewhereInCppGlobalScopeCode()
{
class someInterface
{
public:
virtual void someMethod() = 0;
};
class A : public someInterface
{
public:
void someMethod()
{
std::cout << "A::someMethod()";
}
};
class B : public someInterface
{
public:
void someMethod()
{
std::cout << "B::someMethod()";
}
};
class C : public someInterface
{
public:
void someMethod()
{
std::cout << "C::someMethod()";
}
};
std::vector<someInterface*> ListOfObjectsHavingCommonInterface;
ListOfObjectsHavingCommonInterface.push_back( new A );
ListOfObjectsHavingCommonInterface.push_back( new B );
ListOfObjectsHavingCommonInterface.push_back( new C );
for ( std::vector<someInterface*>::iterator it = ListOfObjectsHavingCommonInterface.begin();
it != ListOfObjectsHavingCommonInterface.end();
++it )
{
(*it)->someMethod();
}
return 0;
}
static int TestSomewhereInCppGlobalScopeCode_Caller = TestSomewhereInCppGlobalScopeCode();