By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,918 Members | 2,258 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,918 IT Pros & Developers. It's quick & easy.

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

P: n/a
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;
}


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 23 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a
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;
}

Jul 23 '05 #2

P: n/a

Siemel Naran wrote:
Here is a question about implicit conversion from T (&)[N] to ptrcarray<T>.
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<T>::ptrcarray(T (&)[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
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 23 '05 #3

P: n/a
msalters wrote in news:1112952308.440758.151330
@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<T>::ptrcarray(T
(&)[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.
--
http://www.victim-prime.dsl.pipex.com/

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 23 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.