Git Product home page Git Product logo

Comments (14)

burnpanck avatar burnpanck commented on August 16, 2024

It appears that this did still work with 2.1.5, but not with 2.2.0.

from outcome.

ned14 avatar ned14 commented on August 16, 2024

I have to say, I would be surprised if this worked in 2.1.5, or at least if it was supposed to. In 2.1.5, the default error type is system_code, which is a move only type with a non-trivial destructor. Therefore, any basic_result with a non-trivially destructible error type would itself be non-trivially destructible, and thus not possible to be a literal type.

I suppose what could have happened here is that you were compiling with C++ 20, whereby if a non-trivial destructor is constexpr, now that works in constexpr?

from outcome.

burnpanck avatar burnpanck commented on August 16, 2024

Indeed, the original code that I discovered this is C++20, and this is what I care about.
However, I have to admit that I don't fully understand the rules that make up a literal type, and how that interacts with returning from constexpr functions.

In my code-base, the error type is outcome::errored_status_code over a custom domain that is derived from outcome::status_code_domain, whose value type is a custom enum. If I recall correctly, the system_code implicitly used in my MVE is an erased int-sized status - does that make system_code non-trivially destructible, while mine is?

In any case, with 2.1.5 I am able to return status_result<std::size_t, errored_status_code<my_domain>> from constexpr functions, but with 2.2.1, I get that above error. Is there a simple error code in outcome which is a literal type and thus would allow for a quick test?

from outcome.

ned14 avatar ned14 commented on August 16, 2024

It was pure luck that system_code happened to work in constexpr if in C++ 20 in your use case. I certainly never intended it to do so, I was writing for C++ 11 (for status code) and C++ 14 (for Outcome) and I was always thinking that the non-trivial destructor made system_code unavailable to any constexpr code. This is the case for all erased status codes, because they may be carrying an erased move only type. So they have to have move only semantics, and therefore non-trivial destructors.

(The pertinent rule for literal types in this situation is that before C++ 20, the type had to have a trivial destructor, but from C++ 20 onwards, the destructor merely needs to be constexpr. Because Outcome v2.1 just happened to default destructors, by happy accident your use case worked)

In any case, with 2.1.5 I am able to return status_result<std::size_t, errored_status_code<my_domain>> from constexpr functions, but with 2.2.1, I get that above error. Is there a simple error code in outcome which is a literal type and thus would allow for a quick test?

Most if not all of the non-erased status codes are literal types, if the payload is a literal type, so will be its status code.

I am minded however to try to fix this for you because status code is before LEWG for standardisation, and LEWG I expect would prefer to see all of status code available to constexpr. I honestly don't know if it's possible however, but I intend to try.

from outcome.

burnpanck avatar burnpanck commented on August 16, 2024

Thanks for looking into this!

I think it makes perfectly sense for non-trivial status types not to be available for constexpr use. My own experience with constexpr and type-erasure is that they don't go well together: The reinterpret_cast you'll likely need somewhere is a hard no. Maybe the new std::bit_cast might help here, but my compiler doesn't support it yet, so I have little experience.

from outcome.

burnpanck avatar burnpanck commented on August 16, 2024

Here is a more accurate minimal failing example (godbolt):

#include <exception>
#include <outcome-experimental.hpp>

namespace outcome = OUTCOME_V2_NAMESPACE;

enum class Status {
    success,
    failure
};

class _status_domain : public outcome::experimental::status_code_domain {
  // We permit status code to call our protected functions
  template <class DomainType>
  friend class system_error2::status_code;
  using _base = outcome::experimental::status_code_domain;

 public:
  // Our value type is Status
  using value_type = Status;

  using _base::string_ref;

  // Always use https://www.random.org/cgi-bin/randbyte?nbytes=8&format=h to
  // create a unique 64 bit value for every unique domain you create!
  _status_domain() noexcept : _base(0x8f9f78114be043e4) {}

  // Default all the copy, move and destruct. This makes the type 100% constexpr
  // in every way which in turns allows the compiler to assume it will not be
  // instantiated at runtime.
  _status_domain(const _status_domain &) = default;
  _status_domain(_status_domain &&) = default;
  _status_domain &operator=(const _status_domain &) = default;
  _status_domain &operator=(_status_domain &&) = default;
  ~_status_domain() = default;

  // Fetch a constexpr instance of this domain
  static inline constexpr const _status_domain &get();

  // Return the name of this domain
  virtual _base::string_ref name() const noexcept override final {
    return _base::string_ref("_status_domain");
  }
};

using errored_status_code = outcome::experimental::errored_status_code<_status_domain>;

constexpr outcome::experimental::status_result<void, errored_status_code> foo(int) {
    return outcome::success();
}

If I understood correctly, the errored_status_code in this example should be a literal type (Status is), though the derived status_result<void, errored_status_code> is not.

from outcome.

ned14 avatar ned14 commented on August 16, 2024

Sorry to not have gotten onto this yet. Awaiting an unoccupied morning before work slot to turn up.

from outcome.

burnpanck avatar burnpanck commented on August 16, 2024

No worries, this is open-source, I wasn't expecting priority support. If it were an urgent need for me, I ought to try to provide a PR myself. Its not urgent though, so I just wanted to make sure that I understand if this is even possible and intended to be supported, or if I better start refactoring my code.

from outcome.

ned14 avatar ned14 commented on August 16, 2024

Try the commit above and let me know how you get on.

from outcome.

ned14 avatar ned14 commented on August 16, 2024

Any news on the above?

from outcome.

burnpanck avatar burnpanck commented on August 16, 2024

Hey @ned14, sorry for the delay. Unfortunately, on my internal code-base, that commit with GCC 10.2 still complains with invalid return type outcome::basic_result<...,system_error2::errored_status_code<my_status_domain>,...> of 'constexpr' function, where my_status_domain has a simple enum class value_type. I'll try to run my minimal failing example locally later today.

from outcome.

burnpanck avatar burnpanck commented on August 16, 2024

Indeed, the above minimal example does compile now. I'll have to dig deeper then to see where the problem in my code is...

from outcome.

ned14 avatar ned14 commented on August 16, 2024

It could be as little as a single missing constexpr anywhere in my code or yours. I find using latest versions of GCC, clang and MSVC can help generate a useful diagnostic. Good luck in finding it!

from outcome.

ned14 avatar ned14 commented on August 16, 2024

I'm going to go ahead and mark this closed. Thanks for the BR!

from outcome.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.