[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lmi] Why is this "=default" ctor needed?
From: |
Greg Chicares |
Subject: |
[lmi] Why is this "=default" ctor needed? |
Date: |
Wed, 20 Jan 2021 21:50:13 +0000 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.4.0 |
Vadim--In branch valyuta/005, this succeeds:
$make $coefficiency unit_tests unit_test_targets=currency_test
but it fails with this patch:
--8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<--
diff --git a/currency.hpp b/currency.hpp
index 9c5558351..dcb11f59a 100644
--- a/currency.hpp
+++ b/currency.hpp
@@ -75,8 +75,8 @@ class LMI_SO currency
public:
using data_type = double;
-// currency() : m_ {0} {} // CURRENCY !! prevents "constexpr currency zero
{};"
- currency() = default;
+ currency() : m_ {0} {} // CURRENCY !! prevents "constexpr currency zero
{};"
+// currency() = default;
explicit currency(data_type z, raw_cents) : m_ {z} {assert_integral(z);}
currency& operator+=(currency const& z) {m_ += z.m_; return *this;}
-->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8--
because:
In file included from /opt/lmi/src/lmi/currency_test.cpp:24:
/opt/lmi/src/lmi/currency.hpp:159:27: error: the type ‘const currency’ of
‘constexpr’ variable ‘C0’ is not literal
159 | inline constexpr currency C0 = {};
| ^~
/opt/lmi/src/lmi/currency.hpp:61:14: note: ‘currency’ is not literal because:
61 | class LMI_SO currency
| ^~~~~~~~
/opt/lmi/src/lmi/currency.hpp:61:14: note: ‘currency’ is not an aggregate,
does not have a trivial default constructor, and has no ‘constexpr’ constructor
that is not a copy or move constructor
I'm surprised by that: I thought that patch would be just fine
(even though I'd agree it's preferable to use "=default" to tell
the compiler to do the work for me). Studying the gcc output:
- of course this isn't an 'aggregate':
- it has a nonstatic data member
- it has a user-declared ctor
- of course I wrote no 'constexpr' ctor
- I've always ignored "triviality"
and "foo f = {}" has always seemed to work, so I figured there was
nothing that I really needed to learn here--until now. Clearly the
problem is that the patch destroys "triviality", but why should
that matter? Perhaps a better explanation is that a constexpr
variable requires a "literal" type; but that's apparently just a
type that allows constexpr, which seems to requires a trivial ctor.
I can figure out what the rule is, through a glass darkly, but...
why does such a rule exist?
AIUI, the empty braces in "C0 = {}" are parsed not as an empty
std::initializer_list, but as an invocation of a default ctor.
But I've provided a default ctor; why can't it be invoked?
Can you tell me how these two default ctors differ:
currency() : m_ {0} {}
currency() = default;
without using the words "literal" or "trivial"?
If I replace "constexpr" with "static const", e.g.:
-inline constexpr currency C0 = {};
+inline static const currency C0 = {};
then it seems to work just fine; but I'd rather have constexpr.
Is there a general guideline I'm supposed to take away from this,
like "always write 'foo() = default'"?
If that's the habit I need to adopt, then do I also actually need
~foo() = default;
and either
foo(foo const&) = default;
foo& operator=(foo const&) = default;
or alternatively something postmodern like
foo(foo) = default;
foo& operator=(foo) = default;
?
- [lmi] Why is this "=default" ctor needed?,
Greg Chicares <=