What trait / concept can guarantee memsetting an object is well defined?











up vote
15
down vote

favorite
3












Let's say I have defined a zero_initialize() function:



template<class T>
T zero_initialize()
{
T result;
std::memset(&result, 0, sizeof(result));
return result;
}

// usage: auto data = zero_initialize<Data>();


Calling zero_initialize() for some types would lead to undefined behavior1, 2. I'm currently enforcing T to verify std::is_pod. With that trait being deprecated in C++20 and the coming of concepts, I'm curious how zero_initialize() should evolve.




  1. What (minimal) trait / concept can guarantee memsetting an object is well defined?

  2. Should I use std::uninitialized_fill instead of std::memset? And why?

  3. Is this function made obsolete by one of C++ initialization syntaxes for a subset of types? Or will it be with the upcoming of future C++ versions?




1)Erase all members of a class.
2)What would be reason for “undefined behaviors” upon using memset on library class(std::string)? [closed]










share|improve this question


















  • 1




    Possible duplicate of Why is std::is_pod deprecated in C++20?
    – Alan Birtles
    yesterday






  • 7




    @AlanBirtles Are you serious?
    – YSC
    yesterday






  • 5




    @AlanBirtles: Not a duplicate. memset is a different beast.
    – Nicol Bolas
    yesterday










  • Sometimes i think these are bots
    – Croll
    yesterday















up vote
15
down vote

favorite
3












Let's say I have defined a zero_initialize() function:



template<class T>
T zero_initialize()
{
T result;
std::memset(&result, 0, sizeof(result));
return result;
}

// usage: auto data = zero_initialize<Data>();


Calling zero_initialize() for some types would lead to undefined behavior1, 2. I'm currently enforcing T to verify std::is_pod. With that trait being deprecated in C++20 and the coming of concepts, I'm curious how zero_initialize() should evolve.




  1. What (minimal) trait / concept can guarantee memsetting an object is well defined?

  2. Should I use std::uninitialized_fill instead of std::memset? And why?

  3. Is this function made obsolete by one of C++ initialization syntaxes for a subset of types? Or will it be with the upcoming of future C++ versions?




1)Erase all members of a class.
2)What would be reason for “undefined behaviors” upon using memset on library class(std::string)? [closed]










share|improve this question


















  • 1




    Possible duplicate of Why is std::is_pod deprecated in C++20?
    – Alan Birtles
    yesterday






  • 7




    @AlanBirtles Are you serious?
    – YSC
    yesterday






  • 5




    @AlanBirtles: Not a duplicate. memset is a different beast.
    – Nicol Bolas
    yesterday










  • Sometimes i think these are bots
    – Croll
    yesterday













up vote
15
down vote

favorite
3









up vote
15
down vote

favorite
3






3





Let's say I have defined a zero_initialize() function:



template<class T>
T zero_initialize()
{
T result;
std::memset(&result, 0, sizeof(result));
return result;
}

// usage: auto data = zero_initialize<Data>();


Calling zero_initialize() for some types would lead to undefined behavior1, 2. I'm currently enforcing T to verify std::is_pod. With that trait being deprecated in C++20 and the coming of concepts, I'm curious how zero_initialize() should evolve.




  1. What (minimal) trait / concept can guarantee memsetting an object is well defined?

  2. Should I use std::uninitialized_fill instead of std::memset? And why?

  3. Is this function made obsolete by one of C++ initialization syntaxes for a subset of types? Or will it be with the upcoming of future C++ versions?




1)Erase all members of a class.
2)What would be reason for “undefined behaviors” upon using memset on library class(std::string)? [closed]










share|improve this question













Let's say I have defined a zero_initialize() function:



template<class T>
T zero_initialize()
{
T result;
std::memset(&result, 0, sizeof(result));
return result;
}

// usage: auto data = zero_initialize<Data>();


Calling zero_initialize() for some types would lead to undefined behavior1, 2. I'm currently enforcing T to verify std::is_pod. With that trait being deprecated in C++20 and the coming of concepts, I'm curious how zero_initialize() should evolve.




  1. What (minimal) trait / concept can guarantee memsetting an object is well defined?

  2. Should I use std::uninitialized_fill instead of std::memset? And why?

  3. Is this function made obsolete by one of C++ initialization syntaxes for a subset of types? Or will it be with the upcoming of future C++ versions?




1)Erase all members of a class.
2)What would be reason for “undefined behaviors” upon using memset on library class(std::string)? [closed]







c++ c++14 metaprogramming sfinae c++20






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked yesterday









YSC

19.2k34591




19.2k34591








  • 1




    Possible duplicate of Why is std::is_pod deprecated in C++20?
    – Alan Birtles
    yesterday






  • 7




    @AlanBirtles Are you serious?
    – YSC
    yesterday






  • 5




    @AlanBirtles: Not a duplicate. memset is a different beast.
    – Nicol Bolas
    yesterday










  • Sometimes i think these are bots
    – Croll
    yesterday














  • 1




    Possible duplicate of Why is std::is_pod deprecated in C++20?
    – Alan Birtles
    yesterday






  • 7




    @AlanBirtles Are you serious?
    – YSC
    yesterday






  • 5




    @AlanBirtles: Not a duplicate. memset is a different beast.
    – Nicol Bolas
    yesterday










  • Sometimes i think these are bots
    – Croll
    yesterday








1




1




Possible duplicate of Why is std::is_pod deprecated in C++20?
– Alan Birtles
yesterday




Possible duplicate of Why is std::is_pod deprecated in C++20?
– Alan Birtles
yesterday




7




7




@AlanBirtles Are you serious?
– YSC
yesterday




@AlanBirtles Are you serious?
– YSC
yesterday




5




5




@AlanBirtles: Not a duplicate. memset is a different beast.
– Nicol Bolas
yesterday




@AlanBirtles: Not a duplicate. memset is a different beast.
– Nicol Bolas
yesterday












Sometimes i think these are bots
– Croll
yesterday




Sometimes i think these are bots
– Croll
yesterday












3 Answers
3






active

oldest

votes

















up vote
19
down vote



accepted










There is technically no object property in C++ which specifies that user code can legally memset a C++ object. And that includes POD, so if you want to be technical, your code was never correct. Even TriviallyCopyable is a property about doing byte-wise copies between existing objects (sometimes through an intermediary byte buffer); it says nothing about inventing data and shoving it into the object's bits.



That being said, you can be reasonably sure this will work if you test is_trivially_copyable and is_trivially_default_constructible. That last one is important, because some TriviallyCopyable types still want to be able to control their contents. For example, such a type could have a private int variable that is always 5, initialized in its default constructor. So long as no code with access to the variable changes it, it will always be 5. The C++ object model guarantees this.



So you can't memset such an object and still get well-defined behavior from the object model.






share|improve this answer

















  • 3




    I appreciate the double answer (language-lawyer/real life exists).
    – YSC
    yesterday


















up vote
8
down vote














What (minimal) trait / concept can guarantee memsetting an object is well defined?




Per the std::memset reference on cppreference the behavior of memset on a non TriviallyCopyable type is undefined. So if it is okay to memset a TriviallyCopyable then you can add a static_assert to your class to check for that like



template<class T>
T zero_initialize()
{
static_assert(std::is_trivial_v<T>, "Error: T must be TriviallyCopyable");
T result;
std::memset(&result, 0, sizeof(result));
return result;
}


Here we use std::is_trivial_v to make sure that not only is the class trivially copyable but it also has a trivial default constructor so we know it is safe to be zero initialized.




Should I use std::uninitialized_fill instead of std::memset? And why?




You don't need to here since you are only initializing a single object.




Is this function made obsolete by one of C++ initialization syntaxes for a subset of types? Or will it be with the upcoming of future C++ versions?




Value or braced initialization does make this function "obsolete". T() and T{} will give you a value initialized T and if T doesn't have a default constructor it will be zero initialized. That means you could rewrite the function as



template<class T>
T zero_initialize()
{
static_assert(std::is_trivial_v<T>, "Error: T must be TriviallyCopyable");
return {};
}





share|improve this answer



















  • 2




    Pardon, but OP used std::memset, not std::memcpy. Does it make a difference though?
    – Rafał Górczewski
    yesterday






  • 1




    @RafałGórczewski OMG. Can't believe I did that. memset has the same requirements so I've just swapped the link and the function names.
    – NathanOliver
    yesterday






  • 2




    It should be noted that TriviallyCopyable only guarantees that byte copying works. Setting the value of a type through a byte array is, as far as I'm aware, not allowed. Plus, TriviallyCopyable does not guarantee default-constructible. So your zero_initialize function isn't allowed. It would only work if you also verified trivially_default_constructible.
    – Nicol Bolas
    yesterday












  • @NicolBolas Good point. I've updated the code to use std::is_trivial_v to guarantee the class is completely trivial.
    – NathanOliver
    yesterday


















up vote
0
down vote













The most general definable trait that guarantees your zero_initialize will actually zero-initialize objects is



template <typename T>
struct can_zero_initialize :
std::bool_constant<std::is_integral_v<
std::remove_cv_t<std::remove_all_extents_t<T>>>> {};


Not too useful. But the only guarantee about bitwise or bytewise representations of fundamental types in the Standard is [basic.fundamental]/7 "The representations of integral types shall define values by use of a pure binary numeration system." There is no guarantee that a floating-point value with all bytes zero is a zero value. There is no guarantee that any pointer or pointer-to-member value with all bytes zero is a null pointer value. (Though both of these are usually true in practice.)



If all non-static members of a trivially-copyable class type are (arrays of) (cv-qualified) integral types, I think that would also be okay, but there's no possible way to test for that, unless reflection comes to C++.






share|improve this answer

















  • 1




    This is true, but I think It does matter to me. Even if for some impl/arch a zero-representation doesn't imply a zero-semantic for some type, zero_initialize() is still well defined. It's up to the user not to assume things.
    – YSC
    yesterday













Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53339268%2fwhat-trait-concept-can-guarantee-memsetting-an-object-is-well-defined%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























3 Answers
3






active

oldest

votes








3 Answers
3






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
19
down vote



accepted










There is technically no object property in C++ which specifies that user code can legally memset a C++ object. And that includes POD, so if you want to be technical, your code was never correct. Even TriviallyCopyable is a property about doing byte-wise copies between existing objects (sometimes through an intermediary byte buffer); it says nothing about inventing data and shoving it into the object's bits.



That being said, you can be reasonably sure this will work if you test is_trivially_copyable and is_trivially_default_constructible. That last one is important, because some TriviallyCopyable types still want to be able to control their contents. For example, such a type could have a private int variable that is always 5, initialized in its default constructor. So long as no code with access to the variable changes it, it will always be 5. The C++ object model guarantees this.



So you can't memset such an object and still get well-defined behavior from the object model.






share|improve this answer

















  • 3




    I appreciate the double answer (language-lawyer/real life exists).
    – YSC
    yesterday















up vote
19
down vote



accepted










There is technically no object property in C++ which specifies that user code can legally memset a C++ object. And that includes POD, so if you want to be technical, your code was never correct. Even TriviallyCopyable is a property about doing byte-wise copies between existing objects (sometimes through an intermediary byte buffer); it says nothing about inventing data and shoving it into the object's bits.



That being said, you can be reasonably sure this will work if you test is_trivially_copyable and is_trivially_default_constructible. That last one is important, because some TriviallyCopyable types still want to be able to control their contents. For example, such a type could have a private int variable that is always 5, initialized in its default constructor. So long as no code with access to the variable changes it, it will always be 5. The C++ object model guarantees this.



So you can't memset such an object and still get well-defined behavior from the object model.






share|improve this answer

















  • 3




    I appreciate the double answer (language-lawyer/real life exists).
    – YSC
    yesterday













up vote
19
down vote



accepted







up vote
19
down vote



accepted






There is technically no object property in C++ which specifies that user code can legally memset a C++ object. And that includes POD, so if you want to be technical, your code was never correct. Even TriviallyCopyable is a property about doing byte-wise copies between existing objects (sometimes through an intermediary byte buffer); it says nothing about inventing data and shoving it into the object's bits.



That being said, you can be reasonably sure this will work if you test is_trivially_copyable and is_trivially_default_constructible. That last one is important, because some TriviallyCopyable types still want to be able to control their contents. For example, such a type could have a private int variable that is always 5, initialized in its default constructor. So long as no code with access to the variable changes it, it will always be 5. The C++ object model guarantees this.



So you can't memset such an object and still get well-defined behavior from the object model.






share|improve this answer












There is technically no object property in C++ which specifies that user code can legally memset a C++ object. And that includes POD, so if you want to be technical, your code was never correct. Even TriviallyCopyable is a property about doing byte-wise copies between existing objects (sometimes through an intermediary byte buffer); it says nothing about inventing data and shoving it into the object's bits.



That being said, you can be reasonably sure this will work if you test is_trivially_copyable and is_trivially_default_constructible. That last one is important, because some TriviallyCopyable types still want to be able to control their contents. For example, such a type could have a private int variable that is always 5, initialized in its default constructor. So long as no code with access to the variable changes it, it will always be 5. The C++ object model guarantees this.



So you can't memset such an object and still get well-defined behavior from the object model.







share|improve this answer












share|improve this answer



share|improve this answer










answered yesterday









Nicol Bolas

278k33455627




278k33455627








  • 3




    I appreciate the double answer (language-lawyer/real life exists).
    – YSC
    yesterday














  • 3




    I appreciate the double answer (language-lawyer/real life exists).
    – YSC
    yesterday








3




3




I appreciate the double answer (language-lawyer/real life exists).
– YSC
yesterday




I appreciate the double answer (language-lawyer/real life exists).
– YSC
yesterday












up vote
8
down vote














What (minimal) trait / concept can guarantee memsetting an object is well defined?




Per the std::memset reference on cppreference the behavior of memset on a non TriviallyCopyable type is undefined. So if it is okay to memset a TriviallyCopyable then you can add a static_assert to your class to check for that like



template<class T>
T zero_initialize()
{
static_assert(std::is_trivial_v<T>, "Error: T must be TriviallyCopyable");
T result;
std::memset(&result, 0, sizeof(result));
return result;
}


Here we use std::is_trivial_v to make sure that not only is the class trivially copyable but it also has a trivial default constructor so we know it is safe to be zero initialized.




Should I use std::uninitialized_fill instead of std::memset? And why?




You don't need to here since you are only initializing a single object.




Is this function made obsolete by one of C++ initialization syntaxes for a subset of types? Or will it be with the upcoming of future C++ versions?




Value or braced initialization does make this function "obsolete". T() and T{} will give you a value initialized T and if T doesn't have a default constructor it will be zero initialized. That means you could rewrite the function as



template<class T>
T zero_initialize()
{
static_assert(std::is_trivial_v<T>, "Error: T must be TriviallyCopyable");
return {};
}





share|improve this answer



















  • 2




    Pardon, but OP used std::memset, not std::memcpy. Does it make a difference though?
    – Rafał Górczewski
    yesterday






  • 1




    @RafałGórczewski OMG. Can't believe I did that. memset has the same requirements so I've just swapped the link and the function names.
    – NathanOliver
    yesterday






  • 2




    It should be noted that TriviallyCopyable only guarantees that byte copying works. Setting the value of a type through a byte array is, as far as I'm aware, not allowed. Plus, TriviallyCopyable does not guarantee default-constructible. So your zero_initialize function isn't allowed. It would only work if you also verified trivially_default_constructible.
    – Nicol Bolas
    yesterday












  • @NicolBolas Good point. I've updated the code to use std::is_trivial_v to guarantee the class is completely trivial.
    – NathanOliver
    yesterday















up vote
8
down vote














What (minimal) trait / concept can guarantee memsetting an object is well defined?




Per the std::memset reference on cppreference the behavior of memset on a non TriviallyCopyable type is undefined. So if it is okay to memset a TriviallyCopyable then you can add a static_assert to your class to check for that like



template<class T>
T zero_initialize()
{
static_assert(std::is_trivial_v<T>, "Error: T must be TriviallyCopyable");
T result;
std::memset(&result, 0, sizeof(result));
return result;
}


Here we use std::is_trivial_v to make sure that not only is the class trivially copyable but it also has a trivial default constructor so we know it is safe to be zero initialized.




Should I use std::uninitialized_fill instead of std::memset? And why?




You don't need to here since you are only initializing a single object.




Is this function made obsolete by one of C++ initialization syntaxes for a subset of types? Or will it be with the upcoming of future C++ versions?




Value or braced initialization does make this function "obsolete". T() and T{} will give you a value initialized T and if T doesn't have a default constructor it will be zero initialized. That means you could rewrite the function as



template<class T>
T zero_initialize()
{
static_assert(std::is_trivial_v<T>, "Error: T must be TriviallyCopyable");
return {};
}





share|improve this answer



















  • 2




    Pardon, but OP used std::memset, not std::memcpy. Does it make a difference though?
    – Rafał Górczewski
    yesterday






  • 1




    @RafałGórczewski OMG. Can't believe I did that. memset has the same requirements so I've just swapped the link and the function names.
    – NathanOliver
    yesterday






  • 2




    It should be noted that TriviallyCopyable only guarantees that byte copying works. Setting the value of a type through a byte array is, as far as I'm aware, not allowed. Plus, TriviallyCopyable does not guarantee default-constructible. So your zero_initialize function isn't allowed. It would only work if you also verified trivially_default_constructible.
    – Nicol Bolas
    yesterday












  • @NicolBolas Good point. I've updated the code to use std::is_trivial_v to guarantee the class is completely trivial.
    – NathanOliver
    yesterday













up vote
8
down vote










up vote
8
down vote










What (minimal) trait / concept can guarantee memsetting an object is well defined?




Per the std::memset reference on cppreference the behavior of memset on a non TriviallyCopyable type is undefined. So if it is okay to memset a TriviallyCopyable then you can add a static_assert to your class to check for that like



template<class T>
T zero_initialize()
{
static_assert(std::is_trivial_v<T>, "Error: T must be TriviallyCopyable");
T result;
std::memset(&result, 0, sizeof(result));
return result;
}


Here we use std::is_trivial_v to make sure that not only is the class trivially copyable but it also has a trivial default constructor so we know it is safe to be zero initialized.




Should I use std::uninitialized_fill instead of std::memset? And why?




You don't need to here since you are only initializing a single object.




Is this function made obsolete by one of C++ initialization syntaxes for a subset of types? Or will it be with the upcoming of future C++ versions?




Value or braced initialization does make this function "obsolete". T() and T{} will give you a value initialized T and if T doesn't have a default constructor it will be zero initialized. That means you could rewrite the function as



template<class T>
T zero_initialize()
{
static_assert(std::is_trivial_v<T>, "Error: T must be TriviallyCopyable");
return {};
}





share|improve this answer















What (minimal) trait / concept can guarantee memsetting an object is well defined?




Per the std::memset reference on cppreference the behavior of memset on a non TriviallyCopyable type is undefined. So if it is okay to memset a TriviallyCopyable then you can add a static_assert to your class to check for that like



template<class T>
T zero_initialize()
{
static_assert(std::is_trivial_v<T>, "Error: T must be TriviallyCopyable");
T result;
std::memset(&result, 0, sizeof(result));
return result;
}


Here we use std::is_trivial_v to make sure that not only is the class trivially copyable but it also has a trivial default constructor so we know it is safe to be zero initialized.




Should I use std::uninitialized_fill instead of std::memset? And why?




You don't need to here since you are only initializing a single object.




Is this function made obsolete by one of C++ initialization syntaxes for a subset of types? Or will it be with the upcoming of future C++ versions?




Value or braced initialization does make this function "obsolete". T() and T{} will give you a value initialized T and if T doesn't have a default constructor it will be zero initialized. That means you could rewrite the function as



template<class T>
T zero_initialize()
{
static_assert(std::is_trivial_v<T>, "Error: T must be TriviallyCopyable");
return {};
}






share|improve this answer














share|improve this answer



share|improve this answer








edited yesterday

























answered yesterday









NathanOliver

82k15111172




82k15111172








  • 2




    Pardon, but OP used std::memset, not std::memcpy. Does it make a difference though?
    – Rafał Górczewski
    yesterday






  • 1




    @RafałGórczewski OMG. Can't believe I did that. memset has the same requirements so I've just swapped the link and the function names.
    – NathanOliver
    yesterday






  • 2




    It should be noted that TriviallyCopyable only guarantees that byte copying works. Setting the value of a type through a byte array is, as far as I'm aware, not allowed. Plus, TriviallyCopyable does not guarantee default-constructible. So your zero_initialize function isn't allowed. It would only work if you also verified trivially_default_constructible.
    – Nicol Bolas
    yesterday












  • @NicolBolas Good point. I've updated the code to use std::is_trivial_v to guarantee the class is completely trivial.
    – NathanOliver
    yesterday














  • 2




    Pardon, but OP used std::memset, not std::memcpy. Does it make a difference though?
    – Rafał Górczewski
    yesterday






  • 1




    @RafałGórczewski OMG. Can't believe I did that. memset has the same requirements so I've just swapped the link and the function names.
    – NathanOliver
    yesterday






  • 2




    It should be noted that TriviallyCopyable only guarantees that byte copying works. Setting the value of a type through a byte array is, as far as I'm aware, not allowed. Plus, TriviallyCopyable does not guarantee default-constructible. So your zero_initialize function isn't allowed. It would only work if you also verified trivially_default_constructible.
    – Nicol Bolas
    yesterday












  • @NicolBolas Good point. I've updated the code to use std::is_trivial_v to guarantee the class is completely trivial.
    – NathanOliver
    yesterday








2




2




Pardon, but OP used std::memset, not std::memcpy. Does it make a difference though?
– Rafał Górczewski
yesterday




Pardon, but OP used std::memset, not std::memcpy. Does it make a difference though?
– Rafał Górczewski
yesterday




1




1




@RafałGórczewski OMG. Can't believe I did that. memset has the same requirements so I've just swapped the link and the function names.
– NathanOliver
yesterday




@RafałGórczewski OMG. Can't believe I did that. memset has the same requirements so I've just swapped the link and the function names.
– NathanOliver
yesterday




2




2




It should be noted that TriviallyCopyable only guarantees that byte copying works. Setting the value of a type through a byte array is, as far as I'm aware, not allowed. Plus, TriviallyCopyable does not guarantee default-constructible. So your zero_initialize function isn't allowed. It would only work if you also verified trivially_default_constructible.
– Nicol Bolas
yesterday






It should be noted that TriviallyCopyable only guarantees that byte copying works. Setting the value of a type through a byte array is, as far as I'm aware, not allowed. Plus, TriviallyCopyable does not guarantee default-constructible. So your zero_initialize function isn't allowed. It would only work if you also verified trivially_default_constructible.
– Nicol Bolas
yesterday














@NicolBolas Good point. I've updated the code to use std::is_trivial_v to guarantee the class is completely trivial.
– NathanOliver
yesterday




@NicolBolas Good point. I've updated the code to use std::is_trivial_v to guarantee the class is completely trivial.
– NathanOliver
yesterday










up vote
0
down vote













The most general definable trait that guarantees your zero_initialize will actually zero-initialize objects is



template <typename T>
struct can_zero_initialize :
std::bool_constant<std::is_integral_v<
std::remove_cv_t<std::remove_all_extents_t<T>>>> {};


Not too useful. But the only guarantee about bitwise or bytewise representations of fundamental types in the Standard is [basic.fundamental]/7 "The representations of integral types shall define values by use of a pure binary numeration system." There is no guarantee that a floating-point value with all bytes zero is a zero value. There is no guarantee that any pointer or pointer-to-member value with all bytes zero is a null pointer value. (Though both of these are usually true in practice.)



If all non-static members of a trivially-copyable class type are (arrays of) (cv-qualified) integral types, I think that would also be okay, but there's no possible way to test for that, unless reflection comes to C++.






share|improve this answer

















  • 1




    This is true, but I think It does matter to me. Even if for some impl/arch a zero-representation doesn't imply a zero-semantic for some type, zero_initialize() is still well defined. It's up to the user not to assume things.
    – YSC
    yesterday

















up vote
0
down vote













The most general definable trait that guarantees your zero_initialize will actually zero-initialize objects is



template <typename T>
struct can_zero_initialize :
std::bool_constant<std::is_integral_v<
std::remove_cv_t<std::remove_all_extents_t<T>>>> {};


Not too useful. But the only guarantee about bitwise or bytewise representations of fundamental types in the Standard is [basic.fundamental]/7 "The representations of integral types shall define values by use of a pure binary numeration system." There is no guarantee that a floating-point value with all bytes zero is a zero value. There is no guarantee that any pointer or pointer-to-member value with all bytes zero is a null pointer value. (Though both of these are usually true in practice.)



If all non-static members of a trivially-copyable class type are (arrays of) (cv-qualified) integral types, I think that would also be okay, but there's no possible way to test for that, unless reflection comes to C++.






share|improve this answer

















  • 1




    This is true, but I think It does matter to me. Even if for some impl/arch a zero-representation doesn't imply a zero-semantic for some type, zero_initialize() is still well defined. It's up to the user not to assume things.
    – YSC
    yesterday















up vote
0
down vote










up vote
0
down vote









The most general definable trait that guarantees your zero_initialize will actually zero-initialize objects is



template <typename T>
struct can_zero_initialize :
std::bool_constant<std::is_integral_v<
std::remove_cv_t<std::remove_all_extents_t<T>>>> {};


Not too useful. But the only guarantee about bitwise or bytewise representations of fundamental types in the Standard is [basic.fundamental]/7 "The representations of integral types shall define values by use of a pure binary numeration system." There is no guarantee that a floating-point value with all bytes zero is a zero value. There is no guarantee that any pointer or pointer-to-member value with all bytes zero is a null pointer value. (Though both of these are usually true in practice.)



If all non-static members of a trivially-copyable class type are (arrays of) (cv-qualified) integral types, I think that would also be okay, but there's no possible way to test for that, unless reflection comes to C++.






share|improve this answer












The most general definable trait that guarantees your zero_initialize will actually zero-initialize objects is



template <typename T>
struct can_zero_initialize :
std::bool_constant<std::is_integral_v<
std::remove_cv_t<std::remove_all_extents_t<T>>>> {};


Not too useful. But the only guarantee about bitwise or bytewise representations of fundamental types in the Standard is [basic.fundamental]/7 "The representations of integral types shall define values by use of a pure binary numeration system." There is no guarantee that a floating-point value with all bytes zero is a zero value. There is no guarantee that any pointer or pointer-to-member value with all bytes zero is a null pointer value. (Though both of these are usually true in practice.)



If all non-static members of a trivially-copyable class type are (arrays of) (cv-qualified) integral types, I think that would also be okay, but there's no possible way to test for that, unless reflection comes to C++.







share|improve this answer












share|improve this answer



share|improve this answer










answered yesterday









aschepler

51k574126




51k574126








  • 1




    This is true, but I think It does matter to me. Even if for some impl/arch a zero-representation doesn't imply a zero-semantic for some type, zero_initialize() is still well defined. It's up to the user not to assume things.
    – YSC
    yesterday
















  • 1




    This is true, but I think It does matter to me. Even if for some impl/arch a zero-representation doesn't imply a zero-semantic for some type, zero_initialize() is still well defined. It's up to the user not to assume things.
    – YSC
    yesterday










1




1




This is true, but I think It does matter to me. Even if for some impl/arch a zero-representation doesn't imply a zero-semantic for some type, zero_initialize() is still well defined. It's up to the user not to assume things.
– YSC
yesterday






This is true, but I think It does matter to me. Even if for some impl/arch a zero-representation doesn't imply a zero-semantic for some type, zero_initialize() is still well defined. It's up to the user not to assume things.
– YSC
yesterday




















 

draft saved


draft discarded



















































 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53339268%2fwhat-trait-concept-can-guarantee-memsetting-an-object-is-well-defined%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

"Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

Alcedinidae

Origin of the phrase “under your belt”?