implicit conversion from T (&)[N] to ptrcarray<T>

S

Siemel Naran

Here is a question about implicit conversion from T (&)[N] to ptrcarray<T>.

I wrote a class

template <class T>
struct ptrcarray
{
T * array;
size_t size;

ptrcarray() : array(NULL), size(0) { }
template <size_t N> ptrcarray(T (&array)[N]) : array(array), size(N) { }
};


Given a function

void f(const ptrcarray<int>& p);

then I expect the following code to compile

int a[] = { 1, 2, 3 };
f(a);

I expect the call to f(a) to convert 'a' of type int(&)[3] to a
ptrcarray<int> because of the implicit constructor ptrcarray<T>::ptrcarray(T
(&)[N]) with T as int and N as 3.

But both Borland and g++ give an error.

e.cc: In function `int realmain(int, const char *const *, const char *const
*)':

Borland 6.0 error ==>
e.cc:33: conversion from `int *' to non-scalar type `ptrcarray<int>'
requested
e.cc:20: in passing argument 1 of `f(const ptrcarray<int> &)'

g++ 2.95.2-6 error ==>
e.cc:33: conversion from `int *' to non-scalar type `ptrcarray<int>'
requested
e.cc:20: in passing argument 1 of `f(const ptrcarray<int> &)'


But if I specify the type explicitly, then it compiles and runs fine on g++
(but on Borland I get an internal compiler error).

int a[] = { 1, 2, 3 };
f(ptrcarray<int>(a));


The question: Are my compilers broken or is my code broken (probably the
latter, but I need to check)?



The full program follows for anyone interested:


//////////////////////////////////////////////////
// realmain.cpp

#include <string>
#include <iostream>

using std::cout;

template <class T>
struct ptrcarray
{
T * array;
size_t size;

ptrcarray() : array(NULL), size(0) { }
template <size_t N> ptrcarray(T (&array)[N]) : array(array), size(N) { }
};

void f(const ptrcarray<int>& p)
{
cout << static_cast<void*>(p.array) << '\t' << p.size << '\n';
}

void g(const ptrcarray<const int>& p)
{
cout << static_cast<const void*>(p.array) << '\t' << p.size << '\n';
}

int realmain(int argc, char const *const * argv, char const *const * env)
{
int a[] = { 1, 2, 3 };
const int b[] = { 1, 2, 3 };
//f(a);
//g(b);
f(ptrcarray<int>(a));
g(ptrcarray<const int>(b));
return 0;
}



//////////////////////////////////////////////////
// main.cpp

#include <exception>

int main(int argc, char * * argv, char * * env)
{
using std::cerr;
try
{
return realmain(
argc,
const_cast<const char *const *>(argv),
const_cast<const char *const *>(env)
);
}
catch (const std::exception& e)
{
cerr << "exception: " << e.what() << "\n";
}
catch (...)
{
cerr << "unhandled exception\n";
}
return 1;
}
 
U

Uenal Mutlu

g++ has some fine, but non-standard, extensions.
Try this. It was compiled using VS6, but should compile with all C++ compilers:

#include <iostream>
using std::cout;

#define NELEMS(arr) (sizeof(arr) / sizeof(arr[0]))

template<typename T> class ptrcarray
{
public:
T* array;
size_t size;

ptrcarray(const T* pArr = 0, size_t N = 0) : array(0), size(N)
{ if (!pArr)
return;
array = new T[size];
memcpy(array, pArr, size * sizeof(*array));
}
~ptrcarray()
{ delete array; }
};

void f(const ptrcarray<int>& p)
{
cout << p.array << '\t' << p.size << '\n';
}

int main(int argc, char* argv[])
{
int a[] = { 1, 2, 3 };
const int b[] = { 1, 2, 3 };

ptrcarray<int> ca1(a, NELEMS(a));
f(ca1);

const ptrcarray<int> ca2(a, NELEMS(a));
f(ca2);

ptrcarray<int> cb1(b, NELEMS(b));
f(cb1);

const ptrcarray<int> cb2(b, NELEMS(b));
f(cb2);

return 0;
}
 
M

msalters

Siemel said:
Here is a question about implicit conversion from T (&)[N] to
ptrcarray said:
I wrote a class

template <class T>
struct ptrcarray
{
template <size_t N> ptrcarray(T (&array)[N]) { }
};
Given a function

void f(const ptrcarray<int>& p);

then I expect the following code to compile

int a[] = { 1, 2, 3 };
f(a);

I expect the call to f(a) to convert 'a' of type int(&)[3] to a
ptrcarray<int> because of the implicit constructor
ptrcarray said:
(&)[N]) with T as int and N as 3.

Won't work. The N cannot be deduced in this context. Basically, you're
trying to mimic template function argument deduction. However, this is
not a function call context but a conversion context. You're looking
for a ctor in ptrcarray<int> that takes an int[3]. That's not
possible, see 14.8.2.1 to 14.8.2.3

Regards,
Michiel Salters
 
R

Rob Williscroft

msalters wrote in @f14g2000cwb.googlegroups.com in comp.lang.c++:
I expect the call to f(a) to convert 'a' of type int(&)[3] to a
ptrcarray<int> because of the implicit constructor
ptrcarray said:
(&)[N]) with T as int and N as 3.

Won't work. The N cannot be deduced in this context. Basically, you're
trying to mimic template function argument deduction. However, this is
not a function call context but a conversion context.

The conversion requires matching a ctor, which requires overload
resolution which (in this case) requires template argument
deduction.
You're looking
for a ctor in ptrcarray<int> that takes an int[3]. That's not
possible, see 14.8.2.1 to 14.8.2.3

#include <ostream>
#include <iostream>
#include <cstdlib>

template <class T>
struct ptrcarray
{
T * array;
size_t size;

ptrcarray() : array(NULL), size(0) { }
template <size_t N> ptrcarray(T (&array)[N]) : array(array), size(N)
{ }
};


void f(const ptrcarray<int>& p) {}


int main()
{
int a[] = { 1, 2, 3 };
f(a);
std::cout << "OK\n";
}

Compiles fine for me, gcc 3.4, bcc 6.0 (preview not builder) and
MSVC 7.1. gcc 3.2 (the ealiest gcc I have access too) failes with
some spurious `const` conversion problem. I didn't try with bcc 5.x,
but from past experience I know this compiler *always* decays array's
to pointers when making function calls, so its never able to deduce N.

To the OP, upgrade your compiler: http://www.mingw.org/

Alas there isn't (AFAICT) an upgrade option for C++ builder (yet)
but they did spam me with a questionare about what what I would
want from ther next version (*) so maybe it will appear at some point.

*) ISO C++ conformance (duh).

Rob.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,142
Latest member
arinsharma
Top