vector<const T(*)> vs. vector<T(*)>

E

eiji.anonremail

Hi all,

I'm facing some uncertainty with const template arguments.
Maybe someone could explain the general strategy.


#include <vector>

int main(int arc, char** argv)
{
std::vector<const int> vec;
const int i = 5;
vec.push_back(i);
vec[0] = 4; //const has gone away

std::vector<const int*> pvec;
const int* pi = new int(5);
pvec.push_back(pi);
*(pvec[0]) = 4; // not possible because const, compile error

return 0;
}

From the first impression, it is not possible to create a vector of
const ints.
But you can do it with pointers.
 
D

dascandy

Hi all,

I'm facing some uncertainty with const template arguments.
Maybe someone could explain the general strategy.

#include <vector>

int main(int arc, char** argv)
{
std::vector<const int> vec;
const int i = 5;
vec.push_back(i);
vec[0] = 4; //const has gone away

std::vector<const int*> pvec;
const int* pi = new int(5);
pvec.push_back(pi);
*(pvec[0]) = 4; // not possible because const, compile error

return 0;

}

From the first impression, it is not possible to create a vector of
const ints.
But you can do it with pointers.

When you take whatever you put into the vector, you get a copy of it.
That means that your copy is not const, no matter what you put in.

The pointers you put in are not const - the ints they point to are. A
const pointer to a changeable int looks like

int * const x;
 
E

eiji.anonremail

When you take whatever you put into the vector, you get a copy of it.
That means that your copy is not const, no matter what you put in.

#include <vector>

template<class T> class MyInt {

T var;

public:
MyInt(T i):var(i){}

T GetT() {return var;}
T& GetTRef() {return var;}
MyInt& operator=(const MyInt& t) {
if (this != &t)
{
var = t.GetT();
}
return *this;
}
};



int main(int arc, char** argv)
{

const int i = 5;
MyInt<const int> mi(i);

//mi.GetTRef() = 4; // error, variable is const


int x = 5;
MyInt<int> mx(x);
mx.GetTRef() = 4; // this works


return 0;
}

Is that really a justification? In that example you can instantiate
MyInt with "const int" and only "int". In both cases the value is
copied, but var is not "int" in both cases.
 
S

Salt_Peter

Hi all,

I'm facing some uncertainty with const template arguments.
Maybe someone could explain the general strategy.

#include <vector>

int main(int arc, char** argv)
{
        std::vector<const int> vec;
        const int i = 5;
        vec.push_back(i);
        vec[0] = 4; //const has gone away

        std::vector<const int*> pvec;
        const int* pi = new int(5);
        pvec.push_back(pi);
        *(pvec[0]) = 4; // not possible because const, compile error

        return 0;

}

From the first impression, it is not possible to create a vector of
const ints.
But you can do it with pointers.

One of the requirements for elements in a container like
std::vector<>, is that those elements be assigneable and copyable. So
const int is a no-no but const int* is fine since that pointer can be
reseated.
 
J

Juha Nieminen

Salt_Peter said:
One of the requirements for elements in a container like
std::vector<>, is that those elements be assigneable and copyable.

Do I remember wrongly that the next standard will introduce the means
to actually allow standard containers to have const elements (in other
words, you can add and remove elements from the container, but you can't
modify the values of existing ones)?
 
X

xdotx

Hi all,

I'm facing some uncertainty with const template arguments.
Maybe someone could explain the general strategy.

#include <vector>

int main(int arc, char** argv)
{
        std::vector<const int> vec;
        const int i = 5;
        vec.push_back(i);
        vec[0] = 4; //const has gone away

        std::vector<const int*> pvec;
        const int* pi = new int(5);
        pvec.push_back(pi);
        *(pvec[0]) = 4; // not possible because const, compile error

        return 0;

}

From the first impression, it is not possible to create a vector of
const ints.
But you can do it with pointers.

This is exactly the reason I always use const on the right (correct)
side, especially when dealing with pointers/references.
'const int' is simply a special case way to write: 'int const'. or
with pointers 'const int *' is 'int const *'
Remember: declarations are read right to left from the variable name.
With this in mind the problem is extremely clear:
int const * - poiter to a constant int (pointer can change, integer
cannot)
int * const - constant pointer to an int (integer can change, pointer
cannot)
 
X

xdotx

  Do I remember wrongly that the next standard will introduce the means
to actually allow standard containers to have const elements (in other
words, you can add and remove elements from the container, but you can't
modify the values of existing ones)?

That seems dangerous. To remove an element would imply destruction,
which is non-const. You can still get const-only access to elements
via const_iterator or const&, or std::set essentially functions like
this.
 
J

James Kanze

I'm facing some uncertainty with const template arguments.
Maybe someone could explain the general strategy.
#include <vector>
int main(int arc, char** argv)
{
std::vector<const int> vec;

This is illegal---undefined behavior according to the standard.
It doesn't compile with my compiler (g++, with the usual
options). And whatever happens if it does compile, you can't
count on it.
const int i = 5;
vec.push_back(i);
vec[0] = 4; //const has gone away

Maybe. Or maybe it core dumps. Or maybe just about anything
else. (I would generally expect it not to compile, but the
standard doesn't require an error message.
std::vector<const int*> pvec;
const int* pi = new int(5);
pvec.push_back(pi);
*(pvec[0]) = 4; // not possible because const, compile error
return 0;
}
From the first impression, it is not possible to create a
vector of const ints. But you can do it with pointers.

What's in the vector cannot be const. You can create a vector
of non-const pointers to const (which is what you did), but not
of const pointers to anything. (You're probably being confused
by a widespread abuse of language. int const* is not a const
pointer, but a pointer to const. A const pointer would be int*
const or int const* const. More generally, just remember that
the const applies to whatever precedes it.)
 
E

eiji.anonremail

Thank you all.

I guess my initial post was somewhat missleading.
I only wanted to say that, when you want to have a vector of const
objects, you have to use pointers!

The "assignable & copyable" rule is the point.
"const T" would be copyable, but not assignable.

I thought it should be possible to allow the creation of a vector of
"const T" because at creation there is no need for an assignment. Or
am I missing something?
 
J

Juha Nieminen

xdotx said:
That seems dangerous. To remove an element would imply destruction,
which is non-const.

Incorrect.

void deleteFoo(const Foo* const foo)
{
delete foo; // Compiles and works just fine.
}
You can still get const-only access to elements
via const_iterator or const&, or std::set essentially functions like
this.

Even if you *can* get const access with the current system, that
doesn't mean it wouldn't be nice if there was a way to *ensure* that the
values of the elements are never modified by accident.
 
R

Richard Herring

Juha Nieminen said:
Incorrect.

void deleteFoo(const Foo* const foo)
{
delete foo; // Compiles and works just fine.
}

Perhaps more to the point, if it's coupled with move semantics (you
referred to the "next standard") removal doesn't imply destruction: the
element just gets moved somewhere else. Similarly, move insertion would
just move an already-created object into the container.
 
J

James Kanze

On Oct 31, 2:56 pm, (e-mail address removed) wrote:

[...]
I thought it should be possible to allow the creation of a
vector of "const T" because at creation there is no need for
an assignment. Or am I missing something?

Yes. That assignment is needed for functions like insert. In
fact, push_back is defined, and often implemented, in terms of
insert, and on seeing insert, the compiler can't know that you
never in fact insert except at the end. So it has to
instantiate the code for both cases, and that code contains
assignments.
 

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,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top