C++ Pointer to const array of const pointers - c++

I've created a const array of const pointers like so:
const char* const sessionList[] = {
dataTable0,
dataTable1,
dataTable2,
dataTable3
};
What is the correct syntax for a regular non-const pointer to this array? I thought it would be const char**, but the compiler thinks otherwise.

If you actually need a pointer to an array, as your title suggests, then this is the syntax:
const char* const (*ptr)[4] = &sessionList;

const char* const sessionList[] = { ... };
is better written as:
char const* const sessionList[] = { ... };
Type of sessionList[0] is char const* const.
Hence, type of &sessionList[0] is char const* const*.
You can use:
char const* const* ptr = &sessionList[0];
or
char const* const* ptr = sessionList;
That declares a pointer to the elements of sessionList. If you want to declare a pointer to the entire array, it needs to be:
char const* const (*ptr)[4] = &sessionList;

The same type as you declared for the array elements, with an extra * added:
const char* const *

Related

How to initialize a non-constant pointer in a constant class with a constant pointer?

I found that this code does not work.
class BinaryData {
public:
int size;
char* bits;
const BinaryData (int _size, const char* _bits) : size(_size), bits(_bits) {}
}
The compiler says that I cannot convert from const char* to char*. However, is this really the case?
What I'm trying to do initialize here is a constant of type const BinaryData. As I know, it's like a class of which fields are given by const int size and const char* const bits. If then, shouldn't things like this have to be allowed?
What I should do if I really have to initialize const BinaryData type value with int and const char*? If it is forbidden, why it has to be forbidden?

reason for pointer to a const pointer when using static_cast

I have tried to solve an exercise from a book but I failed on the static_cast. I used the qsort Method from cstdlib. I have to cast the parameters of my function to a C-String (const char*). But I always get the error message: stattic_cast from type 'const void*' to type 'const char**' casts away qualifiers.
int scmp(const void *s1, const void *s2) {
const char *c1 = (static_cast<const char**>(s1));
const char *c2 = (static_cast<const char**>(s2));
....
}
const char *sfield[] = {"one", "two", "three", "four", "five"};
qsort(sfield, 10, 4, scmp);
The solution is as follows
const char *c1 = *(static_cast<const char* const*>(s1));
What is the reason for the last const and where does it come from? Why I have to cast to a pointer to a constant pointer to char const?
It comes from the origin pointer. static_cast may not discard the const qualifier. So you can only cast void const* to a T const*.
Now, it just so happens that your T is a char const*. You were probably led astray by the leading const in your original code. It does not apply where one may think it applied.
The qsort comparator parameters are pointers to const versions of the elements being compared. In your example the elements being compared are const char *, so a pointer to const of that is const char * const *. Hence the correct version of the code:
int scmp(const void *s1, const void *s2)
{
auto pc1 = static_cast<const char * const *>(s1);
auto pc2 = static_cast<const char * const *>(s2);
char const *c1 = *pc1;
char const *c2 = *pc2;
return strcmp(c1, c2); // or whatever
}
You can do away with pc1, pc2 and apply * operator to the result of the cast if you like .
Perhaps you mistakenly assumed the arguments were the elements being compared, when in fact they are pointers to the elements being compared .
If it is still not clear then maybe it would help to use a symbolic name for the element type:
using ELEMENT_T = const char *;
int scmp(void const *s1, void const *s2)
{
auto pc1 = static_cast<ELEMENT_T const *>(s1);
auto pc2 = static_cast<ELEMENT_T const *>(s2);
ELEMENT_T c1 = *pc1;
ELEMENT_T c2 = *pc2;
return strcmp(c1, c2); // or whatever
}
The same pattern would work for elements that are not pointers (e.g. integer elements).

C++ template type and type of template

What is the type of T if I write something like that:
template<typename T>
class AClass{
private:
T member;
public:
AClass(const T& value = T()) : member(value) {}
};
int main(){
const char* n = "Hello";
AClass<char*> a(n);
return 0;
}
Does T refers to a char or a pointer over a char?
Thanks for your answers
Facts:
T is char * in your example
The example won't compile
Think about your constructor:
AClass(const T& value = T())
What you want is a pointer to const char, that is const char *.
In your constructor you are saying that T is const, thus you are asking for a const pointer to char, that is char * const.
They are actually two different beasts and the compiler complains about the lack of a const (let me say) in the right place in your constructor. That's because a conversion from const char * to char * is not allowed.
Assuming you meant to write
AClass<char*> a('n');
T is a char* (address), but 'n' would resolve to simply char. I don't believe it would compile.

Calling Const function pointer

First off I would like to mention that this works with MSVC but not with clang. I am using Clang with c++11.
I have a function pointer:
typedef void (*Log) (const char* title, const char* msg, const char* file, int line);
I have this struct:
struct FunctionList
{
protected:
static const int kNbrMax = 32;
FunctionList();
bool Add(const void* f);
bool Remove(const void* f);
const void* m_functions[kNbrMax];
};
And this class:
template<typename T>
struct MessageFunctionList
: public FunctionList
{
public:
MessageFunctionList(T defaultFunction)
{
Add(defaultFunction);
}
void Call(const char* title,const char* cause,const char* file,int line)
{
for (unsigned long i = 0;i < m_nbrUsed;++i)
{
reinterpret_cast<T>(m_functions[i])(title,cause,file,line);
}
}
}
I am creating it like so:
static void DefaultLogMessageFunction(const char* title,const char* msg,const char* file,int line)
{
}
MessageFunctionList<Log> functionList(DefaultLogMessageFunction)
But I get the compile time error:
reinterpret_cast from 'const void ' to 'void ()(const char *, const
char *, const char *, int)' casts away qualifiers for line:
reinterpret_cast(m_functions[i])(title,cause,file,line);
So as far as I understand I am trying to cast my const list of functions to a non const value. That is not allowed which makes sense. So I tried the following:
const void* funcPtr = m_functions[i];
const T call = reinterpret_cast<const T>(funcPtr);
call(title, cause, file, line);
But that does not work either.
This works:
void* funcPtr = const_cast<void*>(m_functions[i]);
T call = reinterpret_cast<T>(funcPtr);
call(title,cause,file,line);
But I would like to avoid using a const cast. What am I doing wrong? How can I call this const function? Or is it simply not allowed because it does not know if the function being called is a const function or not? Or perhaps it is because my static function is not a member of a class so it can not be declared const?
You are storing the function pointers as const void*:
const void* m_functions[kNbrMax];
And you are trying to cast them to T and call it using reinterpret_cast:
reinterpret_cast<T>(m_functions[i])(title,cause,file,line);
However, reinterpret_cast cannot remove const qualifier from a type, therefore, you should first remove the const using const_cast:
reinterpret_cast<T>(const_cast<void*>(m_functions[i]))(title,cause,file,line);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
However, please note that const_cast engenders undefined behavior and is unsafe. So is calling a function pointer returned from reinterpret_cast if the original pointer was not actually a T.
Edit:
You can call a const qualified function pointer, however, then the reinterpret_cast should contain the const qualifier:
reinterpret_cast<const T>(m_functions[i])(title,cause,file,line);

Why cant i use static_cast<const char**>(str) instead of (const char**)str?

I have an issue, it doesn't want to cast using static_cast<>. What can it be?
void myCompare(const void *str)
{
const char *ca = *(static_cast<const char**>(str)); //error
const char *a = *(const char **)str; //ok
}
You're casting away const on the second level, which static_cast is not allowed to do (in fact, no "C++" cast apart from const_cast):
void const*
char const* *
// ^^^^^^^^^^^ ^^^^^
// pointee cv-qualifiers
// of pointee
Instead, write
const char *ca = *(static_cast<const char* const*>(str));
The (char const**) cast works here because it is equivalent to a static_cast followed by a const_cast (as per [expr.cast]/(4.3)) - i.e. it was equivalent to
const char *ca = *(const_cast<const char**>(static_cast<const char* const*>(str)));