What trait / concept can guarantee memsetting an object is well defined?
up vote
15
down vote
favorite
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.
- What (minimal) trait / concept can guarantee memsetting an object is well defined?
- Should I use
std::uninitialized_fill
instead ofstd::memset
? And why? - 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
add a comment |
up vote
15
down vote
favorite
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.
- What (minimal) trait / concept can guarantee memsetting an object is well defined?
- Should I use
std::uninitialized_fill
instead ofstd::memset
? And why? - 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
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
add a comment |
up vote
15
down vote
favorite
up vote
15
down vote
favorite
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.
- What (minimal) trait / concept can guarantee memsetting an object is well defined?
- Should I use
std::uninitialized_fill
instead ofstd::memset
? And why? - 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
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.
- What (minimal) trait / concept can guarantee memsetting an object is well defined?
- Should I use
std::uninitialized_fill
instead ofstd::memset
? And why? - 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
c++ c++14 metaprogramming sfinae c++20
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
add a comment |
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
add a comment |
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.
3
I appreciate the double answer (language-lawyer/real life exists).
– YSC
yesterday
add a comment |
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 ofstd::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 {};
}
2
Pardon, but OP usedstd::memset
, notstd::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 yourzero_initialize
function isn't allowed. It would only work if you also verifiedtrivially_default_constructible
.
– Nicol Bolas
yesterday
@NicolBolas Good point. I've updated the code to usestd::is_trivial_v
to guarantee the class is completely trivial.
– NathanOliver
yesterday
add a comment |
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++.
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
add a comment |
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.
3
I appreciate the double answer (language-lawyer/real life exists).
– YSC
yesterday
add a comment |
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.
3
I appreciate the double answer (language-lawyer/real life exists).
– YSC
yesterday
add a comment |
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.
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.
answered yesterday
Nicol Bolas
278k33455627
278k33455627
3
I appreciate the double answer (language-lawyer/real life exists).
– YSC
yesterday
add a comment |
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
add a comment |
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 ofstd::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 {};
}
2
Pardon, but OP usedstd::memset
, notstd::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 yourzero_initialize
function isn't allowed. It would only work if you also verifiedtrivially_default_constructible
.
– Nicol Bolas
yesterday
@NicolBolas Good point. I've updated the code to usestd::is_trivial_v
to guarantee the class is completely trivial.
– NathanOliver
yesterday
add a comment |
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 ofstd::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 {};
}
2
Pardon, but OP usedstd::memset
, notstd::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 yourzero_initialize
function isn't allowed. It would only work if you also verifiedtrivially_default_constructible
.
– Nicol Bolas
yesterday
@NicolBolas Good point. I've updated the code to usestd::is_trivial_v
to guarantee the class is completely trivial.
– NathanOliver
yesterday
add a comment |
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 ofstd::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 {};
}
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 ofstd::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 {};
}
edited yesterday
answered yesterday
NathanOliver
82k15111172
82k15111172
2
Pardon, but OP usedstd::memset
, notstd::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 yourzero_initialize
function isn't allowed. It would only work if you also verifiedtrivially_default_constructible
.
– Nicol Bolas
yesterday
@NicolBolas Good point. I've updated the code to usestd::is_trivial_v
to guarantee the class is completely trivial.
– NathanOliver
yesterday
add a comment |
2
Pardon, but OP usedstd::memset
, notstd::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 yourzero_initialize
function isn't allowed. It would only work if you also verifiedtrivially_default_constructible
.
– Nicol Bolas
yesterday
@NicolBolas Good point. I've updated the code to usestd::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
add a comment |
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++.
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
add a comment |
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++.
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
add a comment |
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++.
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++.
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
add a comment |
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
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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