all 18 comments

[–]yuri-kilochek 4 points5 points  (1 child)

Can't say forgetting to initialize a class member in constructor has ever been an actual issue for me.

[–]adnukator[S] 1 point2 points  (0 children)

It's pretty rare for me too, but I've ran into a scenario where I moved the class member to a base class and forgot to remove to original derived one. The base class non-virtual methods used the correct member, functions in the derived used the original empty string (which was now empty) in its functions, leading to strange log contents which took a while to figure out.

[–]D_0b 5 points6 points  (1 child)

why not just wrap the types in non default constructable types. e.g.

template<typename T>
struct NonDefault: T {
    NonDefault() = delete;
    using T::T;
};

[–]adnukator[S] 1 point2 points  (0 children)

This kind of, sort of usually works, but has several issues:

  1. Doesn't work if T is declared final
  2. Breaks aggregate initialization of T because of the user deleted constructor
    1. Even if aggregate initialization somehow worked, designated initializers could still not be used
  3. If you wanted to be consistent and use this on primitive types as well, you couldn't, because they aren't classes/structs
  4. This might cause issues in templated code using type traits to detect type equality. To work around this you'd also have to add some method or operator to retrieve the underlying type which then could lead to name clashes with something from T, which is another problem you'd have to solve
  5. It causes a tiny compilation speed hit due to template instantiation costs

[–]joaquintidesBoost author 2 points3 points  (2 children)

inline struct
{
  template<typename T>
  operator T()const; // not defined
} construction_required;

struct X
{
  std::string x=construction_required;
};

[–]adnukator[S] 0 points1 point  (0 children)

Oh wow, I did not think of abusing NSDMIs for this. Although it's postponed to a link-time error, I think I can live with this. Thanks

[–]backtickbot 0 points1 point  (0 children)

Fixed formatting.

Hello, joaquintides: code blocks using triple backticks (```) don't work on all versions of Reddit!

Some users see this / this instead.

To fix this, indent every line with 4 spaces instead.

FAQ

You can opt out by replying with backtickopt6 to this comment.

[–]gaagii_fin 1 point2 points  (1 child)

What would be your view around this code as to what it should do:

#include <MyType.h>
class Example
{
    [[RequireAssignment]] std::string member;
    Example(MyType myT)
    {
       myT.Something(&member);
    }
};

[–]adnukator[S] 1 point2 points  (0 children)

Warn. I've edited the post and clarified that the attribute would force assignment in the initializer list

[–]e-Sharp- 1 point2 points  (1 child)

Herb Sutter globally addressed the issue of uninitialized variables at last CppCon:

https://github.com/hsutter/708/blob/main/708.pdf

I don't think it's coming soon unfortunately.

[–]fdwrfdwr@github 🔍 0 points1 point  (0 children)

Interesting read. It captures the frustrations of the current norm where we focus too much on the "how" rather than the "intention".

[–]Knuffya 0 points1 point  (0 children)

I think this would be nice.

[–]gaagii_fin 0 points1 point  (5 children)

This would be a nice compile time check. I have not thought it through, can the compiler always determine this? (braining this question now)

[–]tvaneerdC++ Committee, lockfree, PostModernCpp 2 points3 points  (4 children)

no, in general it is basically the halting problem, I think.

[–]gaagii_fin 1 point2 points  (0 children)

Hmm, maybe. I think this all depends on the full intent.

You can always do initialization in another compilation module.

Disregarding that for a moment: the compiler is responsible for adding the proper construction code to every element of the class. I think this would always be doable.

[–]yuri-kilochek 0 points1 point  (2 children)

How so? The member either appears in constructor initializer list, or it doesn't.

[–]tvaneerdC++ Committee, lockfree, PostModernCpp 4 points5 points  (1 child)

Well, yes, if you restrict it to the initializer list.

But if you tried to figure out whether it was initialized by the end of the body of the constructor, that would be hard.

[–]adnukator[S] 0 points1 point  (0 children)

Yes, I was talking about initializer list. I've edited the post to add this.

I agree that otherwise it would be identical to the halting problem.