Why does std::vector require its elements to be assignable?
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 3 123 LastLast
Results 1 to 15 of 36

Thread: Why does std::vector require its elements to be assignable?

  1. #1
    Join Date
    Apr 2004
    Location
    Canada
    Posts
    1,342

    Why does std::vector require its elements to be assignable?

    Perhaps it's just too early in the morning for me to think straight, but... I can't think of a reason why std::vector would need its elements to be assignable.

    The only operation I can think of that would require the elements to be assignable is the vector's own assignment operator, but why would an operation like push_back() require invoking the assignment operator of its elements? Even in the case of a reallocation, can't the vector use placement new to copy-construct the new elements from the old ones?
    Old Unix programmers never die, they just mv to /dev/null

  2. #2
    Join Date
    Jan 2009
    Posts
    1,689

    Re: Why does std::vector require its elements to be assignable?

    Because you can assign elements.
    Code:
    void setAllToZero(vector<int> & vec){
         foreach(vec, iterator){
              *iterator = 0;
         }
    }

  3. #3
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,694

    Re: Why does std::vector require its elements to be assignable?

    Also
    Code:
    vector<int> vec(10);
    
    vec[3] = 1;
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

  4. #4
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Fairfax, VA
    Posts
    10,885

    Re: Why does std::vector require its elements to be assignable?

    It would be nice if the requirement could be reduced to move-assignable for move-aware types.

  5. #5
    Join Date
    Apr 2004
    Location
    Canada
    Posts
    1,342

    Re: Why does std::vector require its elements to be assignable?

    But suppose you don't do any of those things? Suppose all you do is add elements to the vector using push_back()? Aren't member functions of template classes only instantiated if they're actually used? So shouldn't a piece of code that only calls push_back() compile even if the element type is not assignable?
    Old Unix programmers never die, they just mv to /dev/null

  6. #6
    Join Date
    Aug 2005
    Location
    San Diego, CA
    Posts
    1,054

    Lightbulb Re: Why does std::vector require its elements to be assignable?

    Quote Originally Posted by HighCommander4 View Post
    But suppose you don't do any of those things? Suppose all you do is add elements to the vector using push_back()? Aren't member functions of template classes only instantiated if they're actually used? So shouldn't a piece of code that only calls push_back() compile even if the element type is not assignable?
    No - it is a template which means the the requirements are the same for all types used to instantiate the vector. If an object is created on the stack and then passed to push_back, then the object has to be deep copied. I don't see what the big deal is. Vector isn't special. All sequence containers require the types to be assignable unless you are inserting pointers.

  7. #7
    Join Date
    Aug 2005
    Location
    San Diego, CA
    Posts
    1,054

    Re: Why does std::vector require its elements to be assignable?

    Quote Originally Posted by HighCommander4 View Post

    The only operation I can think of that would require the elements to be assignable is the vector's own assignment operator, but why would an operation like push_back() require invoking the assignment operator of its elements? Even in the case of a reallocation, can't the vector use placement new to copy-construct the new elements from the old ones?
    Placement new? How is that relevant to the question? The object still has to be copied one way or the other and this is done through either the assignment operator or copy constructor.

  8. #8
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Fairfax, VA
    Posts
    10,885

    Re: Why does std::vector require its elements to be assignable?

    Quote Originally Posted by kempofighter View Post
    Placement new? How is that relevant to the question? The object still has to be copied one way or the other and this is done through either the assignment operator or copy constructor.
    But by using placement new, you can do the push_back with the cctor instead of the assignment operator.

    Although, granted, I don't think there are many cases where a type would be copy constructable but not assignable.

  9. #9
    Join Date
    Apr 2004
    Location
    Canada
    Posts
    1,342

    Re: Why does std::vector require its elements to be assignable?

    Quote Originally Posted by kempofighter View Post
    Placement new? How is that relevant to the question? The object still has to be copied one way or the other and this is done through either the assignment operator or copy constructor.
    The element type in my case is copy constructible, just not assignable.

    Quote Originally Posted by Lindley
    Although, granted, I don't think there are many cases where a type would be copy constructable but not assignable.
    Any type with a const or reference member variable falls into this category. In my case, it's map<T, U>::value_type, which is pair<const T, U>. I can, of course, simply store pair<T, U> in the vector, but then when I insert it into the map, an extra copy has to be made to convert it to pair<const T, U>, and it bothers me to have to make this extra copy.
    Old Unix programmers never die, they just mv to /dev/null

  10. #10
    Join Date
    Aug 2005
    Location
    San Diego, CA
    Posts
    1,054

    Re: Why does std::vector require its elements to be assignable?

    Quote Originally Posted by Lindley View Post
    But by using placement new, you can do the push_back with the cctor instead of the assignment operator.

    Although, granted, I don't think there are many cases where a type would be copy constructable but not assignable.

    That's a true statement. The standard agrees with you as well. However sorting and inserting could certainly result in either copy construction or assignment for every object that needs to be shifted around. That is why I think that the question is irrelevant. The containers have many capabilities and for that reason the standard says this:
    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.
    I guess I don't understand what prompted the question. Is it possible that certain uses of the containers may not cause compiler errors because the code doesn't do anything that results in assignment? I guess so. I have never tried that. I guess it depends on the compiler. Perhaps the OP should post an example that produces errors and then explain to us why he thinks that the code ought to compile. That might be an interesting discussion.

  11. #11
    Join Date
    Aug 2005
    Location
    San Diego, CA
    Posts
    1,054

    Re: Why does std::vector require its elements to be assignable?

    Quote Originally Posted by HighCommander4 View Post
    But suppose you don't do any of those things? Suppose all you do is add elements to the vector using push_back()? Aren't member functions of template classes only instantiated if they're actually used? So shouldn't a piece of code that only calls push_back() compile even if the element type is not assignable?
    Interesting question. The answer seems to be no based on the results of testing this example. I received on error on std::fill but I don't even use that algorithm in the program. That is pretty weird and I didn't expect that at all. What examples have you tried to compile and what were your results?

    Code:
    #include <iostream>
    #include <vector>
    struct NonAssignableType
    {
        // default constructors are fine.
        int i;
    private:
        NonAssignableType& operator=(const NonAssignableType& rhs);
    };
    
    int main()
    {
        std::vector<NonAssignableType> naTypeObjects;
        naTypeObjects.push_back(NonAssignableType());
    
        return 0;
    }

    For the rest of the gurus, is that normal for compilers to generate code for all or some of the algorithm templates just because I created an STL container with a user defined type? Perhaps this is my compilers way of enforcing the requirement of the C++ standard that the type be assignable.
    Last edited by kempofighter; June 24th, 2010 at 12:38 PM.

  12. #12
    Join Date
    Aug 2005
    Location
    San Diego, CA
    Posts
    1,054

    Re: Why does std::vector require its elements to be assignable?

    Quote Originally Posted by HighCommander4 View Post

    Any type with a const or reference member variable falls into this category. In my case, it's map<T, U>::value_type, which is pair<const T, U>. I can, of course, simply store pair<T, U> in the vector, but then when I insert it into the map, an extra copy has to be made to convert it to pair<const T, U>, and it bothers me to have to make this extra copy.
    I disagree with that completely. user defined types are always assignable by default. The question is does the default assignment operator work correctly? The only way that the type isn't assignable is if you declare the assignment operator to be non-public. If you have a class with a const member then that member isn't assignable but what about the others? If there are no others then there is nothing to assign and the default assignment operator is benign. So there is no problem there. For trivial user defined types this is never an issue due to the default assignment operator and copy constructor. The only time that your question makes sense is when the copy constructor is needed. If it is needed then you need to implement the assignment operator or disable it by declaring it non-public. The copy/swap idiom makes the design of the assignment operator easy so I am not sure why you would ever want to make an object copyable but not assignable in the first place.

  13. #13
    Join Date
    Apr 2004
    Location
    Canada
    Posts
    1,342

    Re: Why does std::vector require its elements to be assignable?

    Quote Originally Posted by kempofighter View Post
    I disagree with that completely. user defined types are always assignable by default. The question is does the default assignment operator work correctly? The only way that the type isn't assignable is if you declare the assignment operator to be non-public. If you have a class with a const member then that member isn't assignable but what about the others? If there are no others then there is nothing to assign and the default assignment operator is benign. So there is no problem there. For trivial user defined types this is never an issue due to the default assignment operator and copy constructor. The only time that your question makes sense is when the copy constructor is needed. If it is needed then you need to implement the assignment operator or disable it by declaring it non-public. The copy/swap idiom makes the design of the assignment operator easy so I am not sure why you would ever want to make an object copyable but not assignable in the first place.
    I'm not sure I follow. pair<const T, U> is not assignable:

    Code:
    #include <utility>
    using namespace std;
    
    int main()
    {
        pair<const int, int> a;
        pair<const int, int> b;
        a = b;
    }
    Code:
    /usr/include/c++/4.2/bits/stl_pair.h: In member function std::pair<const int, int>& std::pair<const int, int>::operator=(const std::pair<const int, int>&):
    /usr/include/c++/4.2/bits/stl_pair.h:69: error: non-static const member const int std::pair<const int, int>::first, can't use default assignment operator
    test.cpp: In function int main():
    test.cpp:8: note: synthesized method std::pair<const int, int>& std::pair<const int, int>::operator=(const std::pair<const int, int>&) first required here
    Old Unix programmers never die, they just mv to /dev/null

  14. #14
    Join Date
    Jan 2009
    Posts
    1,689

    Re: Why does std::vector require its elements to be assignable?

    Quote Originally Posted by HighCommander4 View Post
    But suppose you don't do any of those things? Suppose all you do is add elements to the vector using push_back()? Aren't member functions of template classes only instantiated if they're actually used? So shouldn't a piece of code that only calls push_back() compile even if the element type is not assignable?
    In that case I would rethink your container needs. Sounds like you need std::stack instead. The right container for the right job.

    You could always write your own vector, for only a few functions, it really wouldn't be that complicated, you could borrow gcc's implementation and strip it to what you need.
    Last edited by ninja9578; June 24th, 2010 at 01:42 PM.

  15. #15
    Join Date
    Apr 2004
    Location
    Canada
    Posts
    1,342

    Re: Why does std::vector require its elements to be assignable?

    Quote Originally Posted by ninja9578 View Post
    In that case I would rethink your container needs. Sounds like you need std::stack instead. The right container for the right job.

    You could always write your own vector, for only a few functions, it really wouldn't be that complicated, you could borrow gcc's implementation and strip it to what you need.
    I need to iterate over the elements after adding them, so stack and queue are out of the question.

    Interestingly, deque seems to work (and meets all my needs). Since the major difference between vector and deque is that deque never has to reallocate its elements, while vector does, this suggests that vector needs to invoke the assignment operator on its elements while reallocating.

    I'm still curious as to why this is - why can't the elements be copied using placement new + copy constructor during reallocation?
    Old Unix programmers never die, they just mv to /dev/null

Page 1 of 3 123 LastLast

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Azure Activities Information Page

Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center