C++ std::fill and std::fill_n error “error C2679”

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP



C++ std::fill and std::fill_n error “error C2679”



What I'm trying to do:



I'm working in a code which is not mine and I'm trying to refactor this. There I have a struct type object, let's call it MY_STRUCTURE with some parameters inside. In the old version of that code, they are using memset to initialize the structure with 0 in all parameters. So, I've tried to change that memset to a more c++ standard approach which is fill or fill_n.



Also, I should mention... There is not an array, is just an object, so all that I'm trying to do is to initialize that object with 0 everywhere.



The memset approach which is working perfectly fine looks like


this:memset(&MyScruct, 0, sizeof(MyScruct));



What have I tried:



I'm trying to use one of fill and fill_n like this:


std::fill(&MyScruct, &MyScruct+ sizeof(MyScruct), 0);



and also


std::fill_n(&MyScruct, sizeof(MyScruct), 0);



where MyScruct is MY_STRUCT MyScruct;


MY_STRUCT MyScruct



In both of this cases I'm getting the same error:



error C2679: binary '=' : no operator found which takes a right-hand
operand of type 'const int' (or there is no acceptable conversion)



Do you have any idea why or what's happening here?





fill and fill_n expect to "fill" an array, as if by doing = 0; for each element in the array. I am guess you actually want to set each byte of your struct to 0; if so then fill and fill_n are not the right tool
– M.M
Aug 13 at 8:18


fill


fill_n


= 0;


fill


fill_n





It would improve the question to explain what you are trying to achieve
– M.M
Aug 13 at 8:18





What is MY_STRUCT?
– miradham
Aug 13 at 8:19


MY_STRUCT





It's happening because fill is trying to do the equivalent of *&MyScruct = 0;.
– molbdnilo
Aug 13 at 8:24



fill


*&MyScruct = 0;





Try an old good memset.
– ZDF
Aug 13 at 8:24




2 Answers
2



In the original code, memset will completely ignore the type system and just write bytes to raw memory, trashing whatever was there before (and I have to question whether the "memset approach which is working perfectly fine" actually works fine, or is really undefined).


memset



On the other hand, std::fill works with the type system, and sets values of the right type. 0 is not a value of the right type (and is not assignable to the type), so you can't "fill" the struct with zeros.


std::fill


0



There is not an array, is just an object



Then you definitely don't want to pass sizeof(MyStruct) because that says how many objects of the type to "fill". You only have one object, not an array with sizeof(MyStruct) elements.


sizeof(MyStruct)


sizeof(MyStruct)



sizeof(MyStruct) is the right argument for memset because that works with bytes, not objects. You need to tell memset how many bytes to write. But it's totally wrong for std::fill and std::fill_n which count in objects, not bytes (unless by chance sizeof(MyStruct)==1, but even then it's a bug waiting to happen).


sizeof(MyStruct)


memset


memset


std::fill


std::fill_n


sizeof(MyStruct)==1



I've tried to change that memset to a more c++ standard approach which is fill or fill_n



std::fill and std::fill_n are the C++ way to assign new values to a sequence of values, not the C++ version of memset. The C++ version of memset is memset!


std::fill


std::fill_n


memset


memset


memset



If you're not trying to reset the values of the struct, just initialize it, then the correct way is just:


MyStruct s = ;



This is perfectly valid C++ and works in any version, from C++98 up to the latest standard. This is simpler and safer and more readable than using memset.


memset





"I have to question whether the "memset approach which is working perfectly fine" actually works fine, or is really undefined": could you elaborate on this? It's safe for POD types, right?
– joe_chip
Aug 13 at 9:34





@joe_chip it's safe for trivially-copyable types. All POD types are trivially-copyable. We don't know if the OP's type is a POD though.
– Jonathan Wakely
Aug 13 at 9:52




If the code was written with memset correctly then there is no reason to change it. fill is not a substitute for memset.


memset


fill


memset



In modern C++ it would be bad to design a class to require memset. However if you are using someone else's class that was designed that way, it is correct to use their class as it was designed.


memset



In modern C++ you would design the class so that value-initialization resets it:


MyScruct = MY_STRUCT;



This code may or may not have the same effect as memset, depending on the details of MY_STRUCT.


memset


MY_STRUCT





I've tried already this but is not working because they are not using c++11, I think... they are using c++03.
– Dumitru Vlad
Aug 13 at 8:31





@DumitruVlad i would recommend just not changing the original code.
– M.M
Aug 13 at 8:32





Ok then, thx for the feedback :)
– Dumitru Vlad
Aug 13 at 8:33






how about assigning 0/default values to MY_STRUCT members in default constructor? Wouldn't it give same effect as MyScruct = MY_STRUCT;?
– miradham
Aug 13 at 8:37


MY_STRUCT


MyScruct = MY_STRUCT;





@miradham he might not want to change the class definition; and even so, that introduces another possible point of failure (e.g. maybe you forget to set one of the members)
– M.M
Aug 13 at 8:39






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Firebase Auth - with Email and Password - Check user already registered

Dynamically update html content plain JS

How to determine optimal route across keyboard