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

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.
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
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
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.
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
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();
}
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
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
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
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.
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();
         ^
Remove unused template line
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.