Skip to content

Latest commit

 

History

History
252 lines (199 loc) · 5.73 KB

306.md

File metadata and controls

252 lines (199 loc) · 5.73 KB
Info

Example

[[nodiscard]] constexpr auto if_hell(bool c1, bool c2) {
    if (c1) {
        if (c2) {
            return true;
        } else {
            throw;
        }
    }

    // ...

    return false;
}

static_assert(not if_hell(false, false));
static_assert(not if_hell(false, true));
assert(throws([]{ if_hell(true, false)); }));
static_assert(if_hell(true, true));

[[nodiscard]] constexpr auto if_heaven(bool c1, bool c2) {
    if (not c1) {
        return false;
    }

    if (not c2) {
        throw;
    }

    // ...

    return true;
}

static_assert(not if_heaven(false, false));
static_assert(not if_heaven(false, true));
assert(throws([]{ if_heaven(true, false)); }));
static_assert(if_heaven(true, true));

https://godbolt.org/z/jEqbM6ozW

Puzzle

  • Can you refactor function foo to avoid if/else hell anti-pattern?
#include <optional>
#include <stdexcept>

// TODO refactor foo to avoid if/else hell anti-pattern
[[nodiscard]] constexpr auto foo(auto trigger, bool is_buy, int price, int quantity) -> std::optional<int> {
  if (is_buy) {
      if (price > 0) {
          if (quantity > 0) {
            const auto filled = trigger(price, quantity);
            if (filled > 0) {
              return filled;
            } else {
              return std::nullopt;
            }
          } else {
              return std::nullopt;
          }
      } else {
          return std::nullopt;
      }
  } else {
      throw std::runtime_error{"not is_buy!"};
  }

  return std::nullopt;
}

#include <https://raw.githubusercontent.com/boost-experimental/ut/master/include/boost/ut.hpp>
#include <tuple>

int main() {
  using namespace boost::ut;

  "foo"_test = [] {
    expect(throws([]{std::ignore = foo([](auto...) { return 0; }, false, 0, 0);}));
    expect(not foo([](auto...) { return 0; }, true, 0, 0));
    expect(not foo([](auto...) { return 0; }, true, 10, 0));
    expect(not foo([](auto...) { return 0; }, true, 10, 10));
    expect(not foo([](auto...) { return 0; }, true, 10, 10));
    expect(1 == foo([](auto...) { return 1; }, true, 10, 10));
    expect(42 == foo([](auto...) { return 42; }, true, 100, 1000));
  };
}

https://godbolt.org/z/fY676KcEs

Solutions

[[nodiscard]] constexpr auto foo(auto trigger, bool is_buy, int price, int quantity) -> std::optional<int> {
    if (not is_buy) {
        throw std::runtime_error{"not is_buy!"};
    }

    if (price <= 0 or quantity <= 0) {
        return std::nullopt;
    }

    const auto filled = trigger(price, quantity);
    if (filled > 0) {
        return filled;
    } else {
        return std::nullopt;
    }
}

https://godbolt.org/z/Pqe3a7xnG

[[nodiscard]] constexpr auto foo(auto trigger, bool is_buy, int price, int quantity) -> std::optional<int>
{
    if (not is_buy)
    {
        throw std::runtime_error{"not is_buy!"};
    }
    if ((price > 0) && (quantity > 0))
    {
        const auto filled = trigger(price, quantity);
        if (filled > 0)
        {
            return filled;
        }
    }

    return std::nullopt;
}

https://godbolt.org/z/31Pf9P83e

[[nodiscard]] constexpr auto foo(auto trigger, bool is_buy, int price, int quantity) -> std::optional<int> {
  if (not is_buy) {
    throw std::runtime_error{"not is_buy!"};
  }

  if (price <= 0 || quantity <= 0)
  {
      return std::nullopt;
  }

  const auto filled = trigger(price, quantity);
  if (filled <= 0) {
    return std::nullopt;
  }
  return filled;
}

https://godbolt.org/z/WoeYxMcn6

[[nodiscard]] constexpr auto foo(auto trigger, bool is_buy, int price, int quantity) -> std::optional<int> {
  if (not is_buy) {
    throw std::runtime_error{"not is_buy!"};
  }

  if (price <= 0 or quantity <= 0) {
    return std::nullopt;
  }

  if (const auto filled = trigger(price, quantity); filled) {
    return filled;
  }

  return std::nullopt;
}

https://godbolt.org/z/4vdeTv7qr

[[nodiscard]] constexpr auto foo(auto trigger, bool is_buy, int price, int quantity) -> std::optional<int> {
  if (not is_buy)
    throw std::runtime_error{"not is_buy!"};
  if (price <= 0 or quantity <=0)
    return std::nullopt;
  const auto filled = trigger(price,quantity);
  if( trigger(price,quantity)>0)
    return filled;
  return std::nullopt;

https://godbolt.org/z/xeM47eTE9

[[nodiscard]] constexpr auto foo(auto trigger, bool is_buy, int price, int quantity) -> std::optional<int> {
  if (not is_buy) {
    throw std::runtime_error{"not is_buy!"};
  }

  if (price <= 0 or quantity <= 0) {
    return std::nullopt;
  }

  const auto filled = trigger(price, quantity);
  return filled > 0 ? std::optional{filled} : std::nullopt;

https://godbolt.org/z/5j81GTe79

[[nodiscard]] constexpr auto foo(auto trigger, bool is_buy, int price,
                                 int quantity) -> std::optional<int> {
    if (!is_buy) {
        throw std::runtime_error{"not is_buy!"};
    }
    if (int filled;
        price > 0 && quantity > 0 && (filled = trigger(price, quantity)) > 0) {
        return filled;
    }
    return std::nullopt;
}

https://godbolt.org/z/E61ovEveo

[[nodiscard]] constexpr auto foo(auto trigger, bool is_buy, int price, int quantity) -> std::optional<int> {

  if (!is_buy){
      throw std::runtime_error{"not is_buy!"};
  }

  decltype(trigger(std::declval<int>(), std::declval<int>())) filled;
  if (price > 0 && quantity > 0 && (filled = trigger(price, quantity)) > 0) {
    return filled;
  }

  return std::nullopt;
}

https://godbolt.org/z/h8ej4KTzo