P: n/a

In the following code, the only way I can figure out to pass an array of
const is by setting the template argument to const in the instanciation
expression. It would be (or seem to me) better if I could set that
qualifier in the function call. Can that be done?
#include <iostream>
using std::ostream;
using std::cout;
template<typename T, unsigned ORDER>
void printArray(T array[], ostream& out=cout)
{
out << "{";
for(unsigned i = 0;i < ORDER; i++ ){
out << array[i];
if(i < ORDER  1){ out << ",";}
}
out << "}\n\n";
}
template <unsigned ORDER, typename T1, typename T2 >
T1 (&aPlus(T1(&t1)[ORDER], T2(&t2)[ORDER]))[ORDER]
{
for(unsigned i = 0;i < ORDER; i++ )
{
t1[i] += t2[i];
}
return t1;
}
template <unsigned ORDER, typename T>
void test_aPlus()
{
T a0[ORDER];
T a1[ORDER];
for(unsigned i = 0; i < ORDER; i++)
{
a0[i]=i;
a1[i]=i*i;
}
aPlus<ORDER, T,T>(a0,a1);
printArray<T,5>(a0);
printArray<T,5>(a1);
T(&ar)[ORDER]=a1;
aPlus<ORDER, T,T>(a0,ar);
printArray<T,5>(a0);
printArray<T,5>(ar);
const T(&car)[ORDER]=a1;
/**
uncomment the following line and it won't compile
**************************/
//aPlus<ORDER,T,T>(a0,car);
aPlus<ORDER,T,const T>(a0,car);
printArray<T,5>(a0);
printArray<const T,5>(car);
}
int main()
{
test_aPlus<5,float>();
return 0;
}

"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true."  Bertrand
Russell  
Share this Question
P: n/a

Steven T. Hatton wrote: In the following code, the only way I can figure out to pass an array of const is by setting the template argument to const in the instanciation expression. It would be (or seem to me) better if I could set that qualifier in the function call. Can that be done?
I'm not sure exactly what you're trying to do, however you can overload
aPlus.  
P: n/a

Gianni Mariani wrote: Steven T. Hatton wrote: In the following code, the only way I can figure out to pass an array of const is by setting the template argument to const in the instanciation expression. It would be (or seem to me) better if I could set that qualifier in the function call. Can that be done?
I'm not sure exactly what you're trying to do, however you can overload aPlus.
Did you compile and run the code? With, and without the commented line
/**
*****uncomment*the*following*line*and*it*won't*com pile
****************************/
**//aPlus<ORDER,T,T>(a0,car);
?
I'm trying to make the second parameter const in this function template:
template <unsigned ORDER, typename T1, typename T2 >
T1 (&aPlus(T1(&t1)[ORDER],**T2(&t2)[ORDER]))[ORDER];
Do you know how to do that?

"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true."  Bertrand
Russell  
P: n/a

Steven T. Hatton wrote: Gianni Mariani wrote:
Steven T. Hatton wrote:
In the following code, the only way I can figure out to pass an array of const is by setting the template argument to const in the instanciation expression. It would be (or seem to me) better if I could set that qualifier in the function call. Can that be done?
I'm not sure exactly what you're trying to do, however you can overload aPlus.
Did you compile and run the code? With, and without the commented line /** uncomment the following line and it won't compile **************************/ //aPlus<ORDER,T,T>(a0,car); ?
I'm trying to make the second parameter const in this function template: template <unsigned ORDER, typename T1, typename T2 > T1 (&aPlus(T1(&t1)[ORDER], T2(&t2)[ORDER]))[ORDER];
Do you know how to do that?
Yes.
Try the code below  note the overloaded aPlus.
Also, you don't need to specify the template parameters, they can be
deduced by the compiler. i.e.
aPlus(a0,car); // this won't work with the overloading below
// but will work with the OP code.
That's what I am confused about, why are you specifying the template
parameters when they can be deduced ?
#include <iostream>
using std::ostream;
using std::cout;
template<typename T, unsigned ORDER>
void printArray(T array[], ostream& out=cout)
{
out << "{";
for(unsigned i = 0;i < ORDER; i++ ){
out << array[i];
if(i < ORDER  1){ out << ",";}
}
out << "}\n\n";
}
template <unsigned ORDER, typename T1, typename T2 >
T1 (&aPlus(T1(&t1)[ORDER], T2(&t2)[ORDER]))[ORDER]
{
for(unsigned i = 0;i < ORDER; i++ )
{
t1[i] += t2[i];
}
return t1;
}
template <unsigned ORDER, typename T1, typename T2 >
T1 (&aPlus(T1(&t1)[ORDER], const T2(&t2)[ORDER]))[ORDER]
{
for(unsigned i = 0;i < ORDER; i++ )
{
t1[i] += t2[i];
}
return t1;
}
template <unsigned ORDER, typename T>
void test_aPlus()
{
T a0[ORDER];
T a1[ORDER];
for(unsigned i = 0; i < ORDER; i++)
{
a0[i]=i;
a1[i]=i*i;
}
aPlus<ORDER, T,T>(a0,a1);
printArray<T,5>(a0);
printArray<T,5>(a1);
T(&ar)[ORDER]=a1;
aPlus<ORDER, T,T>(a0,ar);
printArray<T,5>(a0);
printArray<T,5>(ar);
const T(&car)[ORDER]=a1;
/**
uncomment the following line and it won't compile
**************************/
aPlus<ORDER,T,T>(a0,car);
// aPlus<ORDER,T,const T>(a0,car);
printArray<T,5>(a0);
printArray<const T,5>(car);
}
int main()
{
test_aPlus<5,float>();
return 0;
}  
P: n/a

Gianni Mariani wrote: Steven T. Hatton wrote: Gianni Mariani wrote: Yes.
Try the code below  note the overloaded aPlus.
Also, you don't need to specify the template parameters, they can be deduced by the compiler. i.e.
aPlus(a0,car); // this won't work with the overloading below // but will work with the OP code.
I don't understand what you mean by OP code.
That's what I am confused about, why are you specifying the template parameters when they can be deduced ?
I don't fully understand how that works. In most circumstance where I've
been using templates I've had to specify the actual template parameters
(arguments). #include <iostream> using std::ostream; using std::cout;
template<typename T, unsigned ORDER> void printArray(T array[], ostream& out=cout) { out << "{"; for(unsigned i = 0;i < ORDER; i++ ){ out << array[i]; if(i < ORDER  1){ out << ",";} } out << "}\n\n"; }
template <unsigned ORDER, typename T1, typename T2 > T1 (&aPlus(T1(&t1)[ORDER], T2(&t2)[ORDER]))[ORDER] { for(unsigned i = 0;i < ORDER; i++ ) { t1[i] += t2[i]; } return t1; }
template <unsigned ORDER, typename T1, typename T2 > T1 (&aPlus(T1(&t1)[ORDER], const T2(&t2)[ORDER]))[ORDER] { for(unsigned i = 0;i < ORDER; i++ ) { t1[i] += t2[i]; } return t1; }
OK. I see what you're saying. I guess I was confused by the fact that very
similar code using normal array notation without the references didn't
require any overloading. I guess I've never hit the overloading issue from
this direction before.

"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true."  Bertrand
Russell  
P: n/a

Steven T. Hatton wrote: Gianni Mariani wrote: #include <iostream> using std::ostream; using std::cout;
template<typename T, unsigned ORDER> void printArray(T array[], ostream& out=cout) { out << "{"; for(unsigned i = 0;i < ORDER; i++ ){ out << array[i]; if(i < ORDER  1){ out << ",";} } out << "}\n\n"; }
template <unsigned ORDER, typename T1, typename T2 > T1 (&aPlus(T1(&t1)[ORDER], T2(&t2)[ORDER]))[ORDER] { for(unsigned i = 0;i < ORDER; i++ ) { t1[i] += t2[i]; } return t1; }
template <unsigned ORDER, typename T1, typename T2 > T1 (&aPlus(T1(&t1)[ORDER], const T2(&t2)[ORDER]))[ORDER] { for(unsigned i = 0;i < ORDER; i++ ) { t1[i] += t2[i]; } return t1; }
OK. I see what you're saying. I guess I was confused by the fact that very similar code using normal array notation without the references didn't require any overloading. I guess I've never hit the overloading issue from this direction before.
I'm still confused about what this means. My understanding of making a
parameter const is that the function won't modify it. That's what I want.
Normally, I can pass a nonconst variable as a const reference.
void cfun( const string& cstr)
{
cout << cstr;
}
int main()
{
string str = "This is a nonconst variable\";
cfun(str);
}
So why should I have to overload that function?

"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true."  Bertrand
Russell  
P: n/a

Steven T. Hatton wrote: I'm still confused about what this means. My understanding of making a parameter const is that the function won't modify it. That's what I want. Normally, I can pass a nonconst variable as a const reference.
void cfun( const string& cstr) { cout << cstr; }
int main() {
string str = "This is a nonconst variable\"; cfun(str);
}
So why should I have to overload that function?
In the OP (original post) example, it shows a const object being
assigned to a non const reference, this is not allowed.
C++ can deduce template parameters in function templates AND you can
overload functions which becomes a rather rich area of the language with
all kinds of rope to hang ourselves.
e.g.
template < typename T1, typename T2 > void f1( const T1 &, const T2 & );
template < typename T1, typename T2 > void f2( T1 &, T2 & );
struct X; struct Y;
const X & x;
Y & y;
f1( x, y ); // ==> T1 is X, T2 is Y
f2( x, y ); // ==> T1 is const X, T2 is Y  
P: n/a

"Steven T. Hatton" <su******@setidava.kushan.aa> wrote: Steven T. Hatton wrote: template <unsigned ORDER, typename T1, typename T2 > T1 (&aPlus(T1(&t1)[ORDER], const T2(&t2)[ORDER]))[ORDER] { }
I'm still confused about what this means. My understanding of making a parameter const is that the function won't modify it. That's what I want.
I think what you want is for the referredto things to be const,
not the parameter being const. In fact it is not permitted
to make a reference const (because they cannot be reassigned anyway).
Normally, I can pass a nonconst variable as a const reference.
void cfun( const string& cstr)
That is a reference to const string (not a const reference to string).
If you still don't see the difference then consider:
void foo(int *const ptr)
{ *ptr = 2; }
vs.
void foo(int const *ptr)
{ int const y = 2; ptr = &y; }
In the first one, the parameter is const but the pointedto things
are not; in the second one, it is the other way around.
In your case it is even worse as 'const' could be applied either
to the entire array, or to its members.
int main() { string str = "This is a nonconst variable\"; cfun(str); }
So why should I have to overload that function?
The type 'array of const T2' is not the same as 'const (array of T2)'.  
P: n/a

Gianni Mariani wrote: Steven T. Hatton wrote:
I'm still confused about what this means. My understanding of making a parameter const is that the function won't modify it. That's what I want. Normally, I can pass a nonconst variable as a const reference.
void cfun( const string& cstr) { cout << cstr; }
int main() {
string str = "This is a nonconst variable\"; cfun(str);
}
So why should I have to overload that function? In the OP (original post) example, it shows a const object being assigned to a non const reference, this is not allowed.
template <unsigned ORDER, typename T1, typename T2 >
T1 (&aPlus(T1(&t1)[ORDER], const T2(&t2)[ORDER]))[ORDER]
{
for(unsigned i = 0;i < ORDER; i++ )
{
t1[i] += t2[i];
}
return t1;
}
aPlus(a0,car); // this works
aPlus<ORDER,T,const T>(a0,car); // this works
aPlus<ORDER,T,T>(a0,car); // this doesn't
Why isn't car treated as const in the last statement?
C++ can deduce template parameters in function templates AND you can overload functions which becomes a rather rich area of the language with all kinds of rope to hang ourselves.
e.g.
template < typename T1, typename T2 > void f1( const T1 &, const T2 & ); template < typename T1, typename T2 > void f2( T1 &, T2 & );
struct X; struct Y; const X & x; Y & y; f1( x, y ); // ==> T1 is X, T2 is Y f2( x, y ); // ==> T1 is const X, T2 is Y
I'm not following this code. Is it what you had intended to write?

"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true."  Bertrand
Russell  
P: n/a

Old Wolf wrote: I think what you want is for the referredto things to be const, not the parameter being const. In fact it is not permitted to make a reference const (because they cannot be reassigned anyway).
Sorry, I should have worded that better. I do understand that distinction. So why should I have to overload that function?
The type 'array of const T2' is not the same as 'const (array of T2)'.
The following says aPlus is a function that returns a reference to an array
of type T2:
T1 (&aPlus(T1(&t1)[S],T2(&t2)[S]))[S];
Does this say aPlus is a function that returns a reference to an array of
type const T2:
T1 (&aPlus(T1(&t1)[S],const T2(&t2)[S]))[S];
?

"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true."  Bertrand
Russell  
P: n/a

Steven T. Hatton wrote: Old Wolf wrote:
I think what you want is for the referredto things to be const, not the parameter being const. In fact it is not permitted to make a reference const (because they cannot be reassigned anyway).
Sorry, I should have worded that better. I do understand that distinction.
So why should I have to overload that function?
The type 'array of const T2' is not the same as 'const (array of T2)'.
The following says aPlus is a function that returns a reference to an array of type T2: T1 (&aPlus(T1(&t1)[S],T2(&t2)[S]))[S];
when reading C++ (and C) types you need to start from the identifier.
aPlus is a function that takes parameters t1 and t2 returning a
reference to an array of length S of T1. Does this say aPlus is a function that returns a reference to an array of type const T2: T1 (&aPlus(T1(&t1)[S],const T2(&t2)[S]))[S]; ?
This is the same as the previous one except that t2 is a const T2.  
P: n/a

Steven T. Hatton wrote: Old Wolf wrote:
I think what you want is for the referredto things to be const, not the parameter being const. In fact it is not permitted to make a reference const (because they cannot be reassigned anyway).
Sorry, I should have worded that better. I do understand that distinction.
So why should I have to overload that function?
The type 'array of const T2' is not the same as 'const (array of T2)'.
The following says aPlus is a function that returns a reference to an array of type T2: T1 (&aPlus(T1(&t1)[S],T2(&t2)[S]))[S];
Does this say aPlus is a function that returns a reference to an array of type const T2: T1 (&aPlus(T1(&t1)[S],const T2(&t2)[S]))[S]; ?
Sorry I meant to say "and takes arguments of reference to array of type T1
and reference to array of type (const) T2", not returns ... const ...

"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true."  Bertrand
Russell  
P: n/a

Gianni Mariani wrote: Steven T. Hatton wrote: type const T2: T1 (&aPlus(T1(&t1)[S],const T2(&t2)[S]))[S]; ?
This is the same as the previous one except that t2 is a const T2.
That's what I expected.
T a0[3] = {10,20,30};
T a1[3] = {1,2,3};
T(&ar)[3]=a1;
const T(&car)[3]=a1;
aPlus(a0,car);//works
aPlus<ORDER,T,const*T>(a0,car); //works
aPlus<ORDER,T,T>(a0,car); // won't compile
I would expect the last call to be treated as:
aPlus(T(&a0)[3], const T(&a1)[3]))[3];
I think my confusion is that I don't really understand what the template
parameters are doing.

"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true."  Bertrand
Russell  
P: n/a

Steven T. Hatton wrote:
.... That's what I expected. T a0[3] = {10,20,30}; T a1[3] = {1,2,3}; T(&ar)[3]=a1; const T(&car)[3]=a1;
aPlus(a0,car);//works aPlus<ORDER,T,const T>(a0,car); //works aPlus<ORDER,T,T>(a0,car); // won't compile
I would expect the last call to be treated as: aPlus(T(&a0)[3], const T(&a1)[3]))[3];
I think my confusion is that I don't really understand what the template parameters are doing.
Assuming that this is your funtion aPlus.
template <unsigned ORDER, typename T1, typename T2 >
T1 (&aPlus(T1(&t1)[ORDER], T2(&t2)[ORDER]))[ORDER]
What you're doing is when you instantiate aPlus<ORDER,T,T> is creating a
function like:
T (&aPlus(T(&t1)[ORDER], T(&t2)[ORDER]))[ORDER];
Then you try to pass "car", which is a const T array to a non const T
array reference. The compiler shoul not compile that.  
P: n/a

Gianni Mariani wrote: Steven T. Hatton wrote: ... That's what I expected. T a0[3] = {10,20,30}; T a1[3] = {1,2,3}; T(&ar)[3]=a1; const T(&car)[3]=a1;
aPlus(a0,car);//works aPlus<ORDER,T,const T>(a0,car); //works aPlus<ORDER,T,T>(a0,car); // won't compile
I would expect the last call to be treated as: aPlus(T(&a0)[3], const T(&a1)[3]))[3];
I think my confusion is that I don't really understand what the template parameters are doing.
Assuming that this is your funtion aPlus.
template <unsigned ORDER, typename T1, typename T2 > T1 (&aPlus(T1(&t1)[ORDER], T2(&t2)[ORDER]))[ORDER]
What you're doing is when you instantiate aPlus<ORDER,T,T> is creating a function like:
T (&aPlus(T(&t1)[ORDER], T(&t2)[ORDER]))[ORDER];
Then you try to pass "car", which is a const T array to a non const T array reference. The compiler shoul not compile that.
I now realize that I didn't actually reproduce the problem I thought I had.
The original code wouldn't compile with or without the const. Below is the
code that was originally causing problems. I had been using:
typedef T1 (&rank1T1)[ORDER];
typedef T2 (&rank1T2)[ORDER];
static rank1T1 result(rank1T1 a1, const rank1T2 a2)
template < unsigned REMAINING, unsigned ORDER, typename T1, typename T2,
typename OP>
class Array2OpAssign {
public:
typedef T1 (&rank1T1)[ORDER];
typedef const T2 (&rank1T2)[ORDER];
static rank1T1 result(rank1T1 a1, rank1T2 a2) {
OP op;
a1[ORDER  REMAINING] = op(a1[ORDER  REMAINING], a2[ORDER  REMAINING]);
return Array2OpAssign<REMAINING  1, ORDER, T1, T2, OP>::result(a1,a2);
}
};
template < unsigned ORDER, typename T1, typename T2, typename OP>
class Array2OpAssign<1, ORDER, T1, T2, OP> {
public:
typedef T1 (&rank1T1)[ORDER];
typedef const T2 (&rank1T2)[ORDER];// *NOTE* *DIFFERENCE*
static rank1T1 result (rank1T1 a1, rank1T2 a2){//*NOTE* *DIFFERENCE*
OP op;
a1[ORDER  1] = op(a1[ORDER  1], a2[ORDER  1]);
return a1;
}
};
template <unsigned ORDER, typename T1, typename T2 >
T1 (&array2PlusAssign(T1(&t1)[ORDER], const T2(&t2)[ORDER]))[ORDER]
{
return Array2OpAssign<ORDER,ORDER, T1, T2, Plus<T1, T2> >::result(t1,
t2);
}
template <unsigned ORDER, typename T1, typename T2 >
T1 (&array2MinusAssign(T1(&t1)[ORDER], T2(&t2)[ORDER]))[ORDER]
{
return Array2OpAssign<ORDER,ORDER, T1, T2, Minus<T1, T2> >::result(t1,
t2);
}
}
}
/************************************************** *************************
* Copyright (C) 2004 by Steven T. Hatton *
* ha*****@globalsymmetry.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place  Suite 330, Boston, MA 021111307, USA. *
************************************************** *************************/

"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true."  Bertrand
Russell  
P: n/a

Steven T. Hatton wrote:
....
Does this mean you no longer have a problem ?
.... I now realize that I didn't actually reproduce the problem I thought I had. The original code wouldn't compile with or without the const. Below is the code that was originally causing problems. I had been using: typedef T1 (&rank1T1)[ORDER]; typedef T2 (&rank1T2)[ORDER]; static rank1T1 result(rank1T1 a1, const rank1T2 a2)
template < unsigned REMAINING, unsigned ORDER, typename T1, typename T2, typename OP> class Array2OpAssign { public: typedef T1 (&rank1T1)[ORDER]; typedef const T2 (&rank1T2)[ORDER];
static rank1T1 result(rank1T1 a1, rank1T2 a2) { OP op; a1[ORDER  REMAINING] = op(a1[ORDER  REMAINING], a2[ORDER  REMAINING]); return Array2OpAssign<REMAINING  1, ORDER, T1, T2, OP>::result(a1,a2); } };
template < unsigned ORDER, typename T1, typename T2, typename OP> class Array2OpAssign<1, ORDER, T1, T2, OP> { public: typedef T1 (&rank1T1)[ORDER]; typedef const T2 (&rank1T2)[ORDER];// *NOTE* *DIFFERENCE*
static rank1T1 result (rank1T1 a1, rank1T2 a2){//*NOTE* *DIFFERENCE* OP op; a1[ORDER  1] = op(a1[ORDER  1], a2[ORDER  1]); return a1; } };
template <unsigned ORDER, typename T1, typename T2 > T1 (&array2PlusAssign(T1(&t1)[ORDER], const T2(&t2)[ORDER]))[ORDER] { return Array2OpAssign<ORDER,ORDER, T1, T2, Plus<T1, T2> >::result(t1, t2); }
template <unsigned ORDER, typename T1, typename T2 > T1 (&array2MinusAssign(T1(&t1)[ORDER], T2(&t2)[ORDER]))[ORDER] { return Array2OpAssign<ORDER,ORDER, T1, T2, Minus<T1, T2> >::result(t1, t2); } } }  
P: n/a

Gianni Mariani wrote: Steven T. Hatton wrote: ...
Does this mean you no longer have a problem ?
That's actually a funny question. :D My problems number in the transfinite.
I now have code that performs as I would like it to. I learned a lot from
this experience, and your guidance was invaluable. Thank you...and Victor
too.
I'm trying to read _C++_Templates_:A_Complete_Guide_, but I'm finding it
very difficult. Everytime I look in the book I get new ideas I want to
try, so I'm back to the keyboard and stumbling around for hours before I
turn the page.

"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true."  Bertrand
Russell   This discussion thread is closed Replies have been disabled for this discussion.   Question stats  viewed: 2043
 replies: 16
 date asked: Jul 22 '05
