How to Use Const in Vectors to Allow Adding Elements, But Not Modifications to the Already Added

Can I use const in vectors to allow adding elements, but not modifications to the already added?

Well, in C++0x you can...

In C++03, there is a paragraph 23.1[lib.containers.requirements]/3, which says

The type of objects stored in these components must meet the requirements of CopyConstructible types (20.1.3), and the additional requirements of Assignable types.

This is what's currently preventing you from using const int as a type argument to std::vector.

However, in C++0x, this paragraph is missing, instead, T is required to be Destructible and additional requirements on T are specified per-expression, e.g. v = u on std::vector is only valid if T is MoveConstructible and MoveAssignable.

If I interpret those requirements correctly, it should be possible to instantiate std::vector<const int>, you'll just be missing some of its functionality (which I guess is what you wanted). You can fill it by passing a pair of iterators to the constructor. I think emplace_back() should work as well, though I failed to find explicit requirements on T for it.

You still won't be able to sort the vector in-place though.

vector and const

I've added a few lines to your code. That's sufficient to make it clear why this is disallowed:

void f(vector<const T*>& p)
{
static const T ct;
p.push_back(&ct); // adds a const T* to nonConstVec !
}
int main()
{
vector<T*> nonConstVec;
f(nonConstVec);
nonConstVec.back()->nonConstFunction();
}

std::vector of objects and const-correctness

I'm not sure why nobody said it, but the correct answer is to drop the const, or store A*'s in the vector (using the appropriate smart pointer).

You can give your class terrible semantics by having "copy" invoke UB or doing nothing (and therefore not being a copy), but why all this trouble dancing around UB and bad code? What do you get by making that const? (Hint: Nothing.) Your problem is conceptual: If a class has a const member, the class is const. Objects that are const, fundamentally, cannot be assigned.

Just make it a non-const private, and expose its value immutably. To users, this is equivalent, const-wise. It allows the implicitly generated functions to work just fine.

Why does stackconst string not compile in g++?

The members of a standard container have to be copy assignable or movable (C++11). If the type is const it fails the requirements.

How is it that we're allowed to create a const std::vector without any initializer unlike normal const objects

As we can see that for a const built in type(like int), we must provide an initializer.

That is incorrect. You must ensure that a const object is initialized.

If you do not provide an initializer for an object, that object will undergo the process of default initialization:

To default-initialize an object of type T means:

  • If T is a (possibly cv-qualified) class type ([class]), constructors are considered. The applicable constructors are enumerated ([over.match.ctor]), and the best one for the initializer () is chosen through overload resolution ([over.match]). The constructor thus selected is called, with an empty argument list, to initialize the object.
  • If T is an array type, each element is default-initialized.
  • Otherwise, no initialization is performed.

vector<int> is a class type, so the first option is used. The default constructor will be called to initialize it.

int is not a class type. It is also not an array type. Therefore, no initialization is performed. And if this happens to a const object, the code is ill-formed.

For initializing const object, further rules exist:

If a program calls for the default-initialization of an object of a const-qualified type T, T shall be a const-default-constructible class type or array thereof.

int is not a class type or array of class types at all. So any attempt to create a const-qualified object of type int with default-initialization violates this rule and is ill-formed.

vector<int> happens to follow the rules of const-default-constructible, which is why your code works.

As to whether this particular object is "useful", that's up to you. It's an empty vector<int> which cannot be made non-empty. If that's useful to you in some circumstance, then it is useful.

Const vector of non-const objects

The C++ const-correctness concept is IMO way overrated. What you just discovered is one of the big limitations it has: it doesn't scale by composition.
To be able to create a const vector of non-const objects you need to implement your own vector type. Note that for example even the standard library had to introduce new types for const_iterators.

My suggestion is to use const-correctness where you are forced to, and not everywhere you can. In theory const correctness should help programmers, but comes at a very high cost because of the syntax and is very primitive (just one bit, doesn't scale by composition, even requires code duplication).

Also in my experience this alleged big help is not really that big... most of the errors it catches are related to the const-correctness machinery itself and not to program logic.

Ever wondered why most languages (including ones designed after C++) didn't implement this idea?

vector holding read-only matrices?

What you should do here is create your own matrix class that stores the 5x5 array of data and then create your vector with that.

Adding elements to C++ vector

I change it and it work. it may not be the ideal and correct way but i will let it how it is.

if (wmId == ID_BUTTON) {
//local variables (only for the Button event)
int len_name = GetWindowTextLength(TextBox_Name)+1; //give the lenght value of the text in the textbox
int len_content = GetWindowTextLength(TextBox_content)+1; //give the lenght value of the text in the textbox
wchar_t Text_name[len] = L""; //Wchar is compatible with LPWSTR
wchar_t Text_content[len] = L""; //Wchar is compatible with LPWSTR

// get the text of the Text edit and put it in local variable name and content
GetWindowText(TextBox_Name, (LPWSTR) Text_name, len_name);
GetWindowText(TextBox_content, (LPWSTR)Text_content, len_content);
//verify if the texts are empty
if (len_name == 1 || len_content == 1) {
MessageBox(hWnd, L"name and content can't be empty", L"MessageBox", MB_OK);
}
else {
NameTask.push_back(Text_name); // set name of task in vector of NameTask
ContentTask.push_back(Text_content); // set content of task in vector of ContentTask
ComboBox_AddString(Combobox,Text_name); //set name in combobox
SetWindowText(TextBox_Name, L""); //empty the textbox
SetWindowText(TextBox_content, L""); //empty the textbox



}

}


Related Topics



Leave a reply



Submit