char pointer to array conversions to char pointer to pointer - c++

I have a function:
void add(char const**);
And I invoke it as follow:
template<typename T>
void anotherAdd(T const& t) {
add(&t);
}
...
anotherAdd("some string");
As a result I get the error:
no known conversion for argument 1 from 'const char (*)[10]' to 'const char**'
Why the conversion can't be made?
Because I think the following is true:
"some string" <=> char const* =>
&"some string" <=> char const**

Arrays are not pointers.
This code expects a pointer to a pointer
void add(char const**);
The compiler is telling you that it can't produce a pointer to a pointer because your code has no pointer to point to. You're effectively trying to evaluate &"some string", which has no valid meaning.
This code will work, because it creates the missing char const* that you're trying to take the address of.
template<typename T>
void anotherAdd(T const& t) {
char const *pt = &t; // Now there's a pointer that you can take the address of.
add(&pt);
}

Related

initialise const struct with const pointer

I want to form a struct from const parameters passed to the function. As the parameters are const, i guess the struct has to be const too. However, it does not work with pointers.
The following code compiles (MinGW 4.9.2 32bit)
struct structType_t {
int b;
};
void func1(const int b) {
const structType_t s={b}; // invalid conversion from 'const int*' to 'int*' [-fpermissive]
// do something with s;
}
but with pointers it doesn't:
struct structType_t {
int* b;
};
void func1(const int* b) {
const structType_t s={b}; // invalid conversion from 'const int*' to 'int*' [-fpermissive]
// do something with s;
}
Why does the compiler try to cast away the const here?
So how can i use a const pointer to initialise a const structure?
If you change your struct to hold a const int* you can use it to store the const int* passed to the function, regardless of whether your s is const or not.
struct structType_t {
const int* b;
};
void func1(const int* b) {
const structType_t s={b};
// or
structType_t s2={b};
// do something with s or s2 ...
}
In the first case you are creating a copy of an int. Copy of const int does not have to be const so it works.
In the second case you are creating copy of a pointer to const int and assigning it to a pointer to an int - this is not allowed and that's why it does not compile.

C++ passing function pointer

I have the following function
static void p (){
}
I want to pass a function pointer to p into function x.
void x(void * ptr){
}
I am trying the following, and it is not working.
...
x(ptr);
Note x and p are in different classes.
I am getting the following compiling error.
invalid conversion from 'void (*)()' to 'void*' [-fpermissive]
It needs to be:
void x(void(*function)())
{
// Whatever...
}
If you're using C++11 you can std::function:
void x(std::function<void()> function)
{
// Whatever
}
Let's take a look at the error message:
invalid conversion from 'void (*)()' to 'void*' [-fpermissive]
It means that void* (a data pointer) is the type specified in x,
but void (*)() (a function pointer) is being passed instead.
So change x to
void x(void (*ptr)())
{
}
The answer is in the error message. void* is not a pointer to function, void(*)() (for example) is. You should rewrite x as follows :
void x(void (*ptr)()) {
}
A pointer-to-function is written this way :
Ret (*name)(Params)
Where
Ret is the pointee's return type
name is the name of the pointer
Params is the list ofthe pointee's parameters, as you would write them in its declaration.
Example :
double (*ptr)(int, float)
...can point to a function taking an int and a float and returning a double.
void* is not a function pointer, it's a void pointer.
To declare a function pointer, use void (*ptr)().
We can do some ugly pointer magic, like this:
static void function1( char* c ) {
printf( "%s", c );
}
void function2( void* ptr ) {
void(* func)(char*) = (void(*)(char*))ptr;
func( "a" );
}
int _tmain(int argc, _TCHAR* argv[])
{
void* f = function1;
function2( f );
return 0;
}
This is bad, but it works in such situations.

String literal vs const char* function overload

I have a function that I want to work for const char*'s but it only works for string literals because they are given a special rule to be allowed to initialize arrays. The second overload, foo(const char*) will be preferred for both string literals and const char*s, but my template overload will not work for const char*s.
// Errors for const char*.
template<typename T, size_t n>
void foo(const T (&s)[n])
{
}
// Selected both times if both overloads are present.
void foo(const char*)
{
}
int main()
{
foo("hello");
const char* s = "hello";
foo(s); // Error if foo(const char*) is absent.
}
Is there a way to allow const char*s to initialize arrays?
I've tried this:
template<typename T, size_t n>
void _foo(const T (&s)[n])
{
std::cout << __PRETTY_FUNCTION__;
}
#define _expand(s) #s
#define expand(s) _expand(s)
void foo(const char* s)
{
_foo(expand(s));
}
I think that
const char* s = "hello";
is a pointer to the string literal somewhere in read only memory, and compiler cannot deduce the array size, so it chooses second overload.
You can use
const char s[] = "hello";
No, you can't initialize an array with a pointer. The string literal syntax is a special shorthand for a const char s[] and your working code roughly equivalent to
static const char s[]{'h','e','l','l','o','\0'};
foo(s);
So, you can pass arrays to your template function, including string literals, but you cannot pass pointers, including pointers to string literals.
On the other hand, arrays can decay to pointers, which is why both arrays and pointers can be passed to your second overload.

can't convert from char * to const char *&

I have a funciton like
void foo(const char *&str)
{
cout<<str<<endl;
}
used like:
void main()
{
foo("hello");
char *h = "hello"
foo(h);
}
but both got an error
"can't convert from const char[] to const char *&"
if I change foo to void foo(const char *), there is no error can't I use const char *& as parameter
You got an error because the conversion is illegal. The reason
it is illegal is simple: it breaks const without requiring
a const_cast.
As an example of why it is forbidden, imagine that foo was:
void
foo( char const*& str )
{
str = "abc";
}
int
main()
{
char* h;
foo( h );
*h = '1';
}
If you're not going to modify str in foo, pass by value.
Pass by reference will works if you have char const* const&,
but there's no reason to use it here. It works because the
additional const means that you can bind a temporary to it (as
in the case of foo( "hello" ), where the argument is
a temporary resulting from the conversion of char const[6] to
char const*, and foo( h ) works, because the implicit const
conversions will work (in C++, but not in C!), as long as you
add const everywhere (and not just at one level).
Also, your code also uses a deprecated conversion to initialize
h. You should get a warning here. And void main is an
error, and shouldn't compile.
Edit:
Just to be clear, there's no problem with:
void f( char const*& str );
But you can only call it with an lvalue of type char const*;
anything else will either result in an illegal implicit const
conversion, or try to initialize a non-const reference with an
rvalue, which is illegal.
This will work
int main()
{
const char *h = "hello";
foo(h);
}

Does C++ have no pointer type?

In C++, these two have no difference.
char *pC;
char* pC2;
I thought that the type char and char* have got to be different types and all the C++ programmers had to use this form char* p instead of char *p, because when you do char *p it doesn't seem to specify that the programmer is using a pointer to char.
However, when you take a look at this code below, which is the same as nullptr from C++0x, it seems that T doesn't recognize any pointer type.
const class{
public:
// T is char, not char* in this case.
// T* is char*, but I thought it would be char**
template <class T>
operator T*() const{
cout << "Operator T*() Called" << endl;
return 0;
}
template <class C, class T>
operator T C::*() const{
cout << "Operator C T::*() Called" << endl;
return 0;
}
private:
void operator&() const;
}AAA = {};
int main(){
// operator T*() const is called,
// but it's awkward,
// because it looks like T will be char* type, so T* will be char**
char* pC = AAA;
}
Thanks in advance!
You're correct that char and char* are different types. Whether programmers say char* p or char *p is irrelevant. Those are three separate tokens, and there can be as many or as few spaces between them as you want; it has no effect on the type of p.
When you initialize pC with AAA, the compiler needs to choose a conversion operator from AAA. Since it's initializing a char* variable, it wants operator char*. To make that work, the compiler needs to choose T = char. Since T is char, there's no way T* could be char**.
If you want T to be a pointer type, then use AAA in a context where a pointer-to-pointer type is expected, such as char**. Then T will be char*.
Writing char* p or char *p is just the same thing, both are pointers to a char.