[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [lmi] default-member-initializers vs. is_trivial
From: |
Greg Chicares |
Subject: |
Re: [lmi] default-member-initializers vs. is_trivial |
Date: |
Mon, 19 Apr 2021 20:57:23 +0000 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.9.0 |
On 4/18/21 11:09 PM, Vadim Zeitlin wrote:
> On Sun, 18 Apr 2021 22:50:29 +0000 Greg Chicares <gchicares@sbcglobal.net>
> wrote:
>
> GC> Vadim--Do you happen to know why default member initializers
> GC> prevent a default ctor from being trivial?
>
> Sorry if I'm missing something here, but for me "trivial" informally means
> "doing nothing" and, I believe, this is exactly what the C++ Standard says in
> a more formal way. I.e. a class with a trivial default ctor is like a POD C
> struct -- its ctor just does nothing at all.
Even if it constructs an instance by doing "nothing", it must at least
associate a name with a block of memory. Either that memory is initialized
in some way (e.g., all zeros), or not at all. As an experiment, I tried to
contrive a trivially-default-constructible struct that can't validly be
initialized with all zeros:
#include <type_traits>
enum E {e0 = 3, e1 = 17}; // none of the enumerated values is zero
struct S {E e;};
static_assert(std::is_trivially_constructible_v<S>);
static_assert(std::is_trivially_default_constructible_v<S>);
static_assert(std::is_trivially_copy_constructible_v<S>);
static_assert(std::is_trivially_move_constructible_v<S>);
int main(int, char*[])
{
S s;
std::cout << s.e << std::endl;
return 0;
}
The static assertions succeed, but the stream-output line fails to compile:
error: ‘s.S::e’ is used uninitialized
Then I tried
- struct S {E e;};
+ struct S {float e;}; // 'float' naturally defaults to 0.f
but compiling it with that modification again gives:
‘s.S::e’ is used uninitialized
It builds and runs with this modification:
- std::cout << s.e << std::endl;
+ std::cout << sizeof(s.e) << std::endl;
Is this exactly what's expected? I suppose that's useful for...creating
a vector of objects that cannot be used because they're uninitialized?
Was that the goal? Why would such a goal be desirable? Surely I'm still
missing something.
> And, clearly, if the ctor initializes its members -- as it has to do, if
> they do have initializers -- it must do something, and so can't be trivial.
>
> This reads very tautologically, but isn't it the point? I.e. it's not
> trivial because it can't do nothing while doing something.
I just wasn't expecting that.
> GC> a constexpr value could surely be allowed. For example, given
> GC> struct foo{int i {1};};
> GC> shouldn't a compiler be able to default-construct a 'foo' quite easily?
>
> It probably can, but "easily" is not the same as "trivially".
Okay, my reasoning was that
trivially copyable <--> implementable as memcpy()
so the underlying concept appeared to be
trivially anything <--> translates to something like REPNE MOVSB
or IOW
trivially XXX <--> implementable as memXXX()
from which it might follow that
trivially constructible <-?-> implementable as memset()
but the Standard doesn't even allow memset() here.
- [lmi] default-member-initializers vs. is_trivial, Greg Chicares, 2021/04/18
- Re: [lmi] default-member-initializers vs. is_trivial, Vadim Zeitlin, 2021/04/18
- Re: [lmi] default-member-initializers vs. is_trivial,
Greg Chicares <=
- Re: [lmi] default-member-initializers vs. is_trivial, Vadim Zeitlin, 2021/04/19
- Re: [lmi] default-member-initializers vs. is_trivial, Greg Chicares, 2021/04/19
- Re: [lmi] default-member-initializers vs. is_trivial, Vadim Zeitlin, 2021/04/20
- [lmi] Rule of zero [Was: default-member-initializers vs. is_trivial], Greg Chicares, 2021/04/20
- Re: [lmi] Rule of zero, Vadim Zeitlin, 2021/04/20