--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/8b88f9fd-069f-403b-8252-614e5500e198%40isocpp.org.
Sometimes default construction or move-from leaves an object in a state where it's no use for anything but later assignment.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAGg_6%2BM6guUio-Z2MzBVQZb%2BAabH884SQ_9bEQ0RbG1NbFCfxA%40mail.gmail.com.
Suppose I call it [[empty]], does that change your thoughts at all?My weak aim is to help the optimizer and static analyzer. Weak motivating example follows:A foo() {A a; // where we declared [[empty]] A() = default;auto x = some_input();if ( x == 0 ) a = f0();if ( x != 0 ) a = f1();return a;}A bar() {A a; // where we declared [[empty]] A() = default;auto x = some_input();if ( x == 0 ) a = f0();if ( x == 1 ) a = f1();return a; // Compiler can warn about the potential return of an [[empty]] object}On 29 June 2016 at 23:02, Nevin Liber <ne...@eviloverlord.com> wrote:On 29 June 2016 at 14:08, Jonathan Coe <jb...@me.com> wrote:Sometimes default construction or move-from leaves an object in a state where it's no use for anything but later assignment.
Well, it isn't uninitialized, because you have to be able to destroy the object. We should discourage people from weaken their class invariants; optional<T> is a much better solution for these situations.
On quarta-feira, 29 de junho de 2016 23:13:48 PDT Jonathan Coe wrote:
> Suppose I call it [[empty]], does that change your thoughts at all?
>
> My weak aim is to help the optimizer and static analyzer.
Help doing what?
> A bar() {
> A a; // where we declared [[empty]] A() = default;
> auto x = some_input();
> if ( x == 0 ) a = f0();
> if ( x == 1 ) a = f1();
> return a; // Compiler can warn about the potential return of an [[empty]]
> object
> }
Indeed it can. But the compiler already *does* warn in this case. So what's
the point of the attribute here?
I understand the attribute in the parameter of the move constructor, but if
that one is inline doing:
A (A &&other) { swap(*this, other); }
Then the compiler should already warn on use of the moved-from object.
On Wednesday, June 29, 2016 at 11:28:48 PM UTC+1, Thiago Macieira wrote:On quarta-feira, 29 de junho de 2016 23:13:48 PDT Jonathan Coe wrote:
> Suppose I call it [[empty]], does that change your thoughts at all?
>
> My weak aim is to help the optimizer and static analyzer.
Help doing what?
> A bar() {
> A a; // where we declared [[empty]] A() = default;
> auto x = some_input();
> if ( x == 0 ) a = f0();
> if ( x == 1 ) a = f1();
> return a; // Compiler can warn about the potential return of an [[empty]]
> object
> }
Indeed it can. But the compiler already *does* warn in this case. So what'sI'm not being very clear, sorry.A in this case does have a default constructor that initializes all members, it just puts it into an 'empty' state like a shared pointer with no object or an empty matrix.
Well, it isn't uninitialized, because you have to be able to destroy the object. We should discourage people from weaken their class invariants; optional<T> is a much better solution for these situations.std::optional may be a bad fit because that type says, 'you have to check it'.
I'm interested in cases where being in an empty (or 'uninitialized') state is always a bug.
int* p = nullptr;
int i;
if (someCondition)
p = &i;
*p = 8;
vector<int> ints;
if (someCondition)
ints.push_back(1);
ints.pop_back();
class VoidPointer
{
public:
[[post_state="null"]] explicit VoidPointer() = default;
[[post_state="null"]] explicit VoidPointer(nullptr_t);
explicit VoidPointer(void*);
[[pre_state!="null"]] void* get() const;
[[post_state="null"]] void reset();
...
};
{
VoidPointer p(nullptr);
p.get(); // error
}
{
void* vp = nullptr;
VoidPointer p(vp);
p.get(); // no error? VoidPointer(void*) does not specify post_state.
}
On 2016-06-30 13:04, Thiago Macieira wrote:
> On quinta-feira, 30 de junho de 2016 12:23:19 PDT Matthew Woehlke wrote:
>>> I'm asking about why have a non-trivial constructor that leaves the object
>>> in an unusable state.
>>
>> Define "unusable". I don't think we're talking about cases where the
>> object is actually "unusable", just where its state is "unspecified".
>>
>> For example, QImage(int width, int height, Format format):
>>
>> "This will create a QImage with uninitialized data."
>
> Which is a valid state and the compiler should not warn about.
>
> The example from the OP was more like "any use you make of this prior to
> assigning a new object will have unspecified results". It would be akin to
> having a std::vector created, but the size left uninitialised.
Uh... yeah?
int i;
qDebug() << i; // warning; 'i' is uninitialized
QImage image(64, 64, Qimage::Format_ARGB32);
qDebug() << image.pixel(0, 0); // warning; 'image' is uninitialized
The first warning exists. As I read it, the OP would like the second to
also warn. (You'd need to know what functions fully initialize the
object, though; this probably would not be easy to implement.)
And the above *does* have unspecified results, at least in that the
value you get is unspecified.
--
Matthew
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/nl3ooe%24fmv%241%40ger.gmane.org.
Is there an existing contract system that would have these capabilities for static analysis? How would you state "if this member function throws an exception then the object is left in a partially-formed state" with a contract system?
vector<int> v = {4, 3};
vector<int> j(std::move(v));
v[1] = 4;
A contract system is typically runtime checked (at least everyone I've ever looked at). The reason for the valid but unspecified language is that the object invariants are not violated in a traditional sense. There is no state in the object that can be verified to see if it is unspecified, by definition. In your example, indexing into the object may or may not work. A precondition could be specified as:
T& operator[](size_t i) [[ expects: i < size() ]];
And for an unspecified value size() is unspecified so the precondition may or maynot be satisfied. Adding state would decrease efficiency and would also make nearly everything an optional value. The point at which an object may be unspecified in the code is always known at compile time. Although someone could propose a way to add "unspecified" to a contract system - it would make for an odd mix of runtime and compile time assertions.
One way this could be approached is to start with regular types:
The rules for regular types is that the only valid calls from the regular basis operations on a partially formed object (what the standard calls unspecified) are to destruct and to assign to the object. We could generalize from that to say that it is only valid to write to, or destruct an object.
For the vector example, what would actually fail is the call to size() in the precondition.
Sean
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAOxbGoEA0FD%2BUx147w%2BzJj1dm%3D_nLh%3DidTxOZJik4GCcO8RGgA%40mail.gmail.com.
On 29 June 2016 at 14:08, Jonathan Coe <jb...@me.com> wrote:Sometimes default construction or move-from leaves an object in a state where it's no use for anything but later assignment.
Well, it isn't uninitialized, because you have to be able to destroy the object. We should discourage people from weaken their class invariants; optional<T> is a much better solution for these situations.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/d38370ea-3a97-4fe7-9260-ffb3c6ec399a%40isocpp.org.
--
You received this message because you are subscribed to a topic in the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this topic, visit https://groups.google.com/a/isocpp.org/d/topic/std-proposals/aZG6VRPQ8n8/unsubscribe.
To unsubscribe from this group and all its topics, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAKiZDp1Gdtm98%2BBfVUY9%3DKDRSsXXB8C2suMMNCBKyg0FgbaytA%40mail.gmail.com.
Not necessarily; the moved-from state can often be equivalent to a default state, which does not lead to weakening the invariants. We can make move faster by being more agressive, but in many (most?) cases the moved-from state does not need to be zombie-like (taking «zombie-like» as «for which invariants are broken/ weakened for on which dtor and assignment can still be applied»). Am I misunderstanding what you meant by «zombie» state or «weak invariants»?
std::ofstream f {}; // default constructed file-handle whrapper
f.exceptions ( std::ifstream::failbit | std::ifstream::badbit );
f << 0; // oops cannot write to not-a-file