Date: Mon, 22 Jul 2024 17:45:12 +0200
Hi qiuyili,
the speciifc state, which is interpreted as invalid, should be part of the class declaration, otherwise there would be compatibility and ABI issues.
The binary representation of classes in memory is for many types of classes implementation-defined.
Best,
Sebastian
-----Ursprüngliche Nachricht-----
Von:李 秋逸 via Std-Proposals <std-proposals_at_[hidden]>
Gesendet:Mo 22.07.2024 17:23
Betreff:[std-proposals] 回复: all bytes zero == null object
An:std-proposals_at_[hidden];
CC:李 秋逸 <qiuyili1023_at_[hidden]>;
Maybe we can go further. Here is my solution.
We add a template struct in namespace std.
template<class T>
struct invalid_state; //No definition
We can add a template specialization like this:
template<>
struct std::invalid_state<my_class>
{
static constexpr size_t offset = ... ;
static constexpr unsigned char state[] = {...};
}; //This means from the offset'th to (offset + sizeof(state))'th bytes of an object with type my_class can't be the same as state.
Here is an example:
template<class T>
class my_vector
{
T* data; //8bytes
size_t _size; //8bytes, can't be 0xffffffff
//...
};
template<class T>
struct std::invalid_state<my_vector<T>>
{
static constexpr size_t offset = 8 ;
static constexpr unsigned char state[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
};
Then std::optional< my_vector<T>> can use this to decide whether it has a value.
-----邮件原件-----
发件人: Std-Proposals <std-proposals-bounces_at_[hidden]> 代表 Frederick Virchanza Gotham via Std-Proposals
发送时间: 2024年7月22日 0:51
收件人: std-proposals <std-proposals_at_[hidden]>
抄送: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
主题: [std-proposals] all bytes zero == null object
Typically when implementing a class such as 'std::optional', the size of 'std::optional<T>' is equal to "sizeof(T) + 1u", because one more byte is needed to store a boolean to indicate whether there is a valid object in existence.
We can use "__datasizeof" or "[[no_unique_address]]" in order to try use the tail padding of T to store the boolean, and if we succeed, then sizeof(optional<T>) == sizeof(T).
If T has no tail padding, then we need an extra byte to store the boolean. Unless . . . we had the ability to mark the class 'null_bytes==null_object" as follows:
class T (null_bytes==null_object) {
. . .
};
Marking a class as 'null_bytes==null_object' means that a byte-pattern of all zeroes is a 'null object'. The standard header <type_traits> would then have "std::is_null_bytes_null_object".
So then "std::optional::has_value" could be:
bool optional::has_value(void) noexcept requires is_null_bytes_null_object_v<T>
{
return (0u == *storage) && !memcmp(storage, storage + 1u,
sizeof(storage) - 1u);
}
Another effect of marking a class as 'null_bytes==null_object' would be that the destructor doesn't get called. For instance the following program won't crash:
struct T (null==0) {
int a, b, c;
~T(void) { *(int*)nullptr = 666; }
};
int main(void)
{
T var = {0,0,0};
}
The above program doesn't have undefined behaviour, because the destructor is treated as though it were written:
~T(void)
{
char const *const p = (char*)this;
if ( (0u == *p) && !memcmp(p, p + 1u, sizeof(*this) - 1u) ) return;
*(int*)nullptr = 0;
}
--
Std-Proposals mailing list
Std-Proposals_at_[hidden]
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
--
Std-Proposals mailing list
Std-Proposals_at_[hidden]
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Received on 2024-07-22 15:45:14