Make t2 const: T1 (&aPlus(T1(&t1)[S],T2(&t2)[S]))[S]

  • Thread starter Steven T. Hatton
  • Start date
S

Steven T. Hatton

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::eek:stream;
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;
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 += t2;
}
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;
a1=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
 
G

Gianni Mariani

Steven said:
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.
 
S

Steven T. Hatton

Gianni said:
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?
--
"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
 
G

Gianni Mariani

Steven said:
Gianni Mariani wrote:

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::eek:stream;
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;
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 += t2;
}
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 += t2;
}
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;
a1=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;
}
 
S

Steven T. Hatton

Gianni said:
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::eek:stream;
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;
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 += t2;
}
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 += t2;
}
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
 
S

Steven T. Hatton

Steven said:
Gianni Mariani wrote:
#include <iostream>
using std::eek:stream;
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;
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 += t2;
}
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 += t2;
}
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 non-const variable as a const reference.

void cfun( const string& cstr)
{
cout << cstr;
}

int main()
{

string str = "This is a non-const 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
 
G

Gianni Mariani

Steven said:
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 non-const variable as a const reference.

void cfun( const string& cstr)
{
cout << cstr;
}

int main()
{

string str = "This is a non-const 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
 
O

Old Wolf

Steven T. Hatton said:
Steven said:
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 referred-to 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 non-const 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 pointed-to 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 non-const 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)'.
 
S

Steven T. Hatton

Gianni said:
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 += t2;
}
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
 
S

Steven T. Hatton

Old said:
I think what you want is for the referred-to 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.
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),T2(&t2)));

Does this say aPlus is a function that returns a reference to an array of
type const T2:
T1 (&aPlus(T1(&t1),const T2(&t2)));
?
--
"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
 
G

Gianni Mariani

Steven said:
Old Wolf wrote:

I think what you want is for the referred-to 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.

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),T2(&t2)));


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),const T2(&t2)));
?


This is the same as the previous one except that t2 is a const T2.
 
S

Steven T. Hatton

Steven said:
Old said:
I think what you want is for the referred-to 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.
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),T2(&t2)));

Does this say aPlus is a function that returns a reference to an array of
type const T2:
T1 (&aPlus(T1(&t1),const T2(&t2)));
?


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
 
S

Steven T. Hatton

Gianni said:
Steven T. Hatton wrote:
type const T2:
T1 (&aPlus(T1(&t1),const T2(&t2)));
?


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
 
G

Gianni Mariani

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.
 
S

Steven T. Hatton

Gianni said:
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 *
* (e-mail address removed) *
* *
* 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 02111-1307, 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
 
S

Steven T. Hatton

Gianni said:
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
 

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

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top