compile error: invalid conversion from 'Row<3>* const*' to 'RowBase* const*' [-fpermissive]

Oct 2, 2014 at 7:48am
I am getting this compile error on line 34:
invalid conversion from 'Row<3>* const*' to 'RowBase* const*' [-fpermissive]

What is invalid about the conversion?

template_ptrArray.cpp:
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>

class RowBase
{
  public:
    virtual void scan() = 0;
};

template< int N >			//Non-type Template Arguments
class Row : public RowBase
{
	private:
		int samples[ N ];	//array of samples
	public:
		void scan()
		{
			for (int i=0; i<N; i++)
			{
				samples[i] = i;
				std::cout << samples[i];
			}
		}
};

class Matrix
{
	private:
		RowBase*const *const ptrsRows; //array of row pointers
	public:
		template<int N>
		Matrix(Row<N>*const *const pr): ptrsRows(pr) {}
};

//********** ROWS ***********
const int N=3;
Row< N > row0;
Row< N > row1;

//********** MATRIX ***********
Row< N >* const ptrsRows[] = { &row0, &row1 }; //array of row pointers
Matrix matrix(ptrsRows);

int main()
{
	row1.scan();
}

Output:
template_ptrArray.cpp: In instantiation of Matrix::Matrix(Row<N>* const*) [with int N = 3]':
template_ptrArray.cpp:41:23:   required from here
template_ptrArray.cpp:31:46: error: invalid conversion from 'Row<3>* const*' to 'RowBase* const*' [-fpermissive]
   Matrix(Row<N>*const *const pr): ptrsRows(pr) {}

Similar error messages posted online have incongruent number dereference operators e.g.
invalid conversion from 'int*' to 'int'
But in my error message, the number of dereference operators match.

This is a continuation of the example that MiiNiPaa helped me with on http://www.cplusplus.com/forum/beginner/143783/

Thank you.
Oct 2, 2014 at 8:06am
Pointer types are not polymorphic. If you have a pointer that points to a A* you can't make it point to a B* even if B is a subclass of A.

1
2
3
4
5
6
7
8
9
10
11
struct A {};
struct B : A {};

int main()
{
	A ** a;
	B ** b;
	
	// error: invalid conversion from ‘B**’ to ‘A**’
	a = b; 
}
Last edited on Oct 2, 2014 at 8:07am
Oct 2, 2014 at 8:14am
Just manually cast it.

1
2
3
4
A* a = new A();
B* b = static_cast<B*>(a);
//or
b = (B*)a;


The other guy who posted sees your question differently to I, seeing as you're wanting to cast from derived class to a base class.
Last edited on Oct 2, 2014 at 8:15am
Oct 2, 2014 at 8:37am
DO not ever manually cast pointers to arrays. Ever.

Imagine what happens if base class have size of 2 and derived 3
1
2
3
4
5
6
7
8
9
10
11
//Memory layouts of Someclass t[] = {x, y, z} and pointer returned by t[1]
//for base 
XXYYZZ
  ↑
//For derived
XXXYYYZZZ
   ↑

//If we cast derived* to base* and make t[1]:
XXXYYYZZZ
  ↑
You see, compiler will return pointer to not the beginning of second objec, but inside first.
To solve the need to store in single array objects of different types, you can make proxy which would contain [smart]pointer to actual objects. Or use std::reference_wrapper. Or store array of pointers to base type.
Oct 2, 2014 at 8:40am
Hmm, I think you can solve your problems by using RowBase instead if Row<N> in most places.

1
2
3
4
5
6
7
8
9
10
11
12
class Matrix
{
	private:
		RowBase*const *const ptrsRows; //array of row pointers
	public:
		Matrix(RowBase*const *const pr): ptrsRows(pr) {}
};

...

RowBase* const ptrsRows[] = { &row0, &row1 }; //array of row pointers
Matrix matrix(ptrsRows);
Last edited on Oct 2, 2014 at 8:41am
Oct 2, 2014 at 9:03am
Thanks Peter87 and Krisando.

So I tried to use static_cast but got this error:
template_ptrArray.cpp:41:66: error: invalid static_cast from type 'Row<3>* const [2]' to type 'RowBase* const*'
 RowBase*const *const pr = static_cast <RowBase*const *> (ptrsRows)
                                                                  ^

I thought an array can always be implicitly converted to the pointer of the proper type.

template_ptrArray.cpp with static_cast on line 41:
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>

class RowBase
{
  public:
    virtual void scan() = 0;
};

template< int N >			//Non-type Template Arguments
class Row : public RowBase
{
	private:
		int samples[ N ];	//array of samples
	public:
		void scan()
		{
			for (int i=0; i<N; i++)
			{
				samples[i] = i;
				std::cout << samples[i];
			}
		}
};

class Matrix
{
	private:
		RowBase*const *const ptrsRows; //array of row pointers
	public:
		template<int N>
		Matrix(RowBase*const *const pr): ptrsRows(pr) {}
};

//********** ROWS ***********
const int N=3;
Row< N > row0;
Row< N > row1;

//********** MATRIX ***********
Row< N >* const ptrsRows[] = { &row0, &row1 }; //array of row pointers
RowBase*const *const pr = static_cast <RowBase*const *> (ptrsRows)
Matrix matrix(pr);

int main()
{
	row1.scan();
}
Oct 2, 2014 at 9:18am
Please disregard my previous post.

I like Peter87's last solution because it looks simple.
But it gets this syntax error:
template_ptrArray.cpp:41:23: error: no matching function for call to 'Matrix::Matrix(RowBase* [2])'
 Matrix matrix(ptrsRows);
                       ^


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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>

class RowBase
{
  public:
    virtual void scan() = 0;
};

template< int N >			//Non-type Template Arguments
class Row : public RowBase
{
	private:
		int samples[ N ];	//array of samples
	public:
		void scan()
		{
			for (int i=0; i<N; i++)
			{
				samples[i] = i;
				std::cout << samples[i];
			}
		}
};

class Matrix
{
	private:
		RowBase** ptrsRows; //array of row pointers
	public:
		template<int N>
		Matrix(RowBase** pr): ptrsRows(pr) {}
};

//********** ROWS ***********
const int N=3;
Row< N > row0;
Row< N > row1;

//********** MATRIX ***********
RowBase*  ptrsRows[] = { &row0, &row1 }; //array of row pointers
Matrix matrix(ptrsRows);

int main()
{
	row1.scan();
}

Output:
template_ptrArray.cpp:41:23: error: no matching function for call to 'Matrix::Matrix(RowBase* [2])'
 Matrix matrix(ptrsRows);
                       ^
template_ptrArray.cpp:41:23: note: candidates are:
template_ptrArray.cpp:31:3: note: template<int N> Matrix::Matrix(RowBase**)
   Matrix(RowBase** pr): ptrsRows(pr) {}
   ^
template_ptrArray.cpp:31:3: note:   template argument deduction/substitution fai
led:
template_ptrArray.cpp:41:23: note:   couldn't deduce template parameter 'N'
 Matrix matrix(ptrsRows);
                       ^
template_ptrArray.cpp:25:7: note: Matrix::Matrix(const Matrix&)
 class Matrix
       ^
template_ptrArray.cpp:25:7: note:   no known conversion for argument 1 from 'Row
Base* [2]' to 'const Matrix&'
Last edited on Oct 2, 2014 at 9:25am
Oct 2, 2014 at 9:20am
I thought an array can always be implicitly converted to the pointer of the proper type.
No, arrays cannot be converted to the pointer of the base type. It is dangerous. If anyone will suggest reinterpret_cast to solve that, just smack them in the face. I posted why earlier. You can initialize RowBase array with derived pointers:
RowBase* pr[] = {&row0, &row1};

Why do you need to use pointers, C-arrays and other hard-to-handle stuff?
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
class Matrix
{
	public:  //For testing
		const std::vector<RowBase*> ptrsRows; //Still waiting for dynarray
	public:
		template<int N>
		Matrix(Row<N>* pr): ptrsRows{pr} {}

		template<typename T, int G>
		Matrix(T const (&pr)[G]): ptrsRows(std::begin(pr), std::end(pr)) {}
};

//********** ROWS ***********
const int N=13;
Row< N > row0;
Row< 4 > row1;

//********** MATRIX ***********
RowBase* ptrsRows[] = { &row0, &row1 }; //array of row pointers
Matrix matrix(ptrsRows);

int main()
{
	matrix.ptrsRows[1]->scan();
}
Or make a constructor receiving a pair of iterators. Best solution, really.
Last edited on Oct 2, 2014 at 10:06am
Oct 2, 2014 at 8:33pm
Hi MiiNiPaa,
The code will be Arduino firmware for a keyboard library.
Arduino does not have access to Vector, Boost libraries or C++11.

The scan() function scans the keyboard matrix.
I already have the firmware running on a keyboard.
Now I am porting the keyboard firmware to a Keyboard library to make writing custom keyboard firmware easy.
But moving the Row class into a library is proving to be difficult.
Last edited on Oct 2, 2014 at 8:39pm
Oct 2, 2014 at 11:48pm
Arduino does not have access to Vector
Just take vector implementation from some compiler library, cut parts which you do not need and you now have something vector-like. Or just write it yourself.
Oct 3, 2014 at 6:15am
MiiNiPaa,
I might try something vector-like if I can't figure out this error message.

Line 42 gets this syntax error:
no matching function for call to 'Matrix::Matrix(RowBase**&)'

Where is the '&' at end of error message coming from?

Thank you.

template_ptrArray.cpp:
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <iostream>

class RowBase
{
  public:
    virtual void scan() = 0;
};

template< int N >			//Non-type Template Arguments
class Row : public RowBase
{
	private:
		int samples[ N ];	//array of samples
	public:
		void scan()
		{
			for (int i=0; i<N; i++)
			{
				samples[i] = i;
				std::cout << samples[i];
			}
		}
};

class Matrix
{
	private:
		RowBase** ptrsRows; //array of row pointers
	public:
		template<int N>
		Matrix(RowBase** pr): ptrsRows(pr) {}
};

//********** ROWS ***********
const int N=3;
Row< N > row0;
Row< N > row1;

//********** MATRIX ***********
RowBase*  ptrsRows[] = { &row0, &row1 }; //array of row pointers
RowBase** pr = static_cast <RowBase**> (ptrsRows); //cast array to pointer
Matrix matrix(pr); //error: no matching function for call to 'Matrix::Matrix(RowBase**&)'
			//where is the '&' at end of error message coming from?
//Matrix matrix(ptrsRows);

int main()
{
	matrix.ptrsRows[0]->scan();
	//matrix.ptrsRows[1]->scan();
	//row1.scan();
}


Output:
template_ptrArray.cpp:42:17: error: no matching function for call to 'Matrix::Matrix(RowBase**&)'
 Matrix matrix(pr);
                 ^
template_ptrArray.cpp:42:17: note: candidates are:
template_ptrArray.cpp:31:3: note: template<int N> Matrix::Matrix(RowBase**)
   Matrix(RowBase** pr): ptrsRows(pr) {}
   ^
template_ptrArray.cpp:31:3: note:   template argument deduction/substitution failed:
template_ptrArray.cpp:42:17: note:   couldn't deduce template parameter 'N'
 Matrix matrix(pr);
                 ^
template_ptrArray.cpp:25:7: note: Matrix::Matrix(const Matrix&)
 class Matrix
       ^
template_ptrArray.cpp:25:7: note:   no known conversion for argument 1 from 'Row
Base**' to 'const Matrix&'
template_ptrArray.cpp: In function 'int main()':
template_ptrArray.cpp:28:13: error: 'RowBase** Matrix::ptrsRows' is private
   RowBase** ptrsRows; //array of row pointers
             ^
template_ptrArray.cpp:47:9: error: within this context
  matrix.ptrsRows[0]->scan();
         ^
Oct 3, 2014 at 8:01am
Remove unused template line
Oct 3, 2014 at 8:27am
That was it!
Thank you so much for your help MiiniPaa.

This works:
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>

class RowBase
{
  public:
    virtual void scan() = 0;
};

template< int N >			//Non-type Template Arguments
class Row : public RowBase
{
	private:
		int samples[ N ];	//array of samples
	public:
		void scan()
		{
			for (int i=0; i<N; i++)
			{
				samples[i] = i;
				std::cout << samples[i];
			}
				std::cout << std::endl;
		}
};

class Matrix
{
	private:
		RowBase** ptrsRows;	 //array of row pointers
	public:
		Matrix(RowBase** pr): ptrsRows(pr) {}
};

//********** ROWS ***********
Row< 2 > row0;
Row< 5 > row1;

//********** MATRIX ***********
RowBase*  ptrsRows[] = { &row0, &row1 }; //array of row pointers
Matrix matrix(ptrsRows);

int main()
{
	row0.scan();
	row1.scan();
}


Output:
01
01234
Topic archived. No new replies allowed.