ned14 / outcome

Provides very lightweight outcome<T> and result<T> (non-Boost edition)
https://ned14.github.io/outcome
Other
675 stars 62 forks source link

How to in-place construct immovable-type object with private constructor? #296

Closed tuanthien closed 4 months ago

tuanthien commented 4 months ago

I have this setup where i need to in-place construct an immovable-type object but the constructor is private. I couldn't find any document about do this. I tried to friend a few suspicious internal classes, it but didn't work. Thank you.

I could make the constructor public and document it being internal but I curious if there is a better solution.

#include "SystemCode.hpp"

namespace Eao {

struct Immovable;

using ResultType = OUTCOME_V2_NAMESPACE::basic_result<
    Immovable, Eao::SystemStatus,
    OUTCOME_V2_NAMESPACE::experimental::policy::all_narrow>;

struct Immovable {
 public:
  friend ResultType MakeImmovable();

  template <class R, class EC, class NoValuePolicy>
  friend class OUTCOME_V2_NAMESPACE::detail::basic_result_storage;
  template <class R, class EC>
  friend class OUTCOME_V2_NAMESPACE::detail::value_storage_trivial;
  template <class R, class EC>
  friend class OUTCOME_V2_NAMESPACE::detail::value_storage_nontrivial;

  Immovable() = delete;
  Immovable(const Immovable&) = delete;
  Immovable(Immovable&&) = delete;

 private:
  Immovable(int) {}
};

ResultType MakeImmovable() {
  return ResultType(OUTCOME_V2_NAMESPACE::in_place_type<Immovable>, 5);
}

}  // namespace Eao

int main() { std::ignore = Eao::MakeImmovable(); }

https://compiler-explorer.com/z/634o77aaz

ned14 commented 4 months ago

Similar to the STL, if you make your constructors private for an immovable type, pre-17 you just need to make your constructors public or use some tag to prevent normal code calling them.

Post-17 you can have a friend helper function as copy elision is guaranteed.

My current workplace we use a lot of immovable objects within results and whilst awkward, it does work. We are C++ 20 however.

tuanthien commented 4 months ago

Does outcome have such helper function available? i couldn't find those functions to friend them in my immovable class. I feel like i misunderstanding something.

ned14 commented 4 months ago

I'm saying that like with the STL, it's on you and your code to make it constructible by containing types if it is immovable.

For example, if you wanted to put an immovable type into std::pair<>, the STL offers you an emplacement option and an assignment option. You need to figure out some technique best for your code to make use of the emplacement option.

I know you're looking to friend internal types to skip this issue, but neither the STL nor Boost nor Outcome would support you doing that.

tuanthien commented 4 months ago

I'm saying that like with the STL, it's on you and your code to make it constructible by containing types if it is immovable.

For example, if you wanted to put an immovable type into std::pair<>, the STL offers you an emplacement option and an assignment option. You need to figure out some technique best for your code to make use of the emplacement option.

I know you're looking to friend internal types to skip this issue, but neither the STL nor Boost nor Outcome would support you doing that.

I see the actual problem now, thank you for spending time explain this to me. Happy lunar new year!

BurningEnlightenment commented 4 months ago

In case you haven't seen it; there is a small section in the documentation which covers this case: Result returning constructors