ned14 / outcome Goto Github PK
View Code? Open in Web Editor NEWProvides very lightweight outcome<T> and result<T> (non-Boost edition)
Home Page: https://ned14.github.io/outcome
License: Other
Provides very lightweight outcome<T> and result<T> (non-Boost edition)
Home Page: https://ned14.github.io/outcome
License: Other
This self-contained example failed to compile (MSVC14)
#include <boost/monad/future.hpp>
int main()
{
boost::monad::lightweight_futures::future<void> f;
f.get();
return 0;
}
If you change void
to int
, it compiles w/o problem. Is future<void>
not supported?
I am trying to compile Boost.Outcome on MinGW distro: a platform for running GCC (6.3.0) on Windows (7). Here are details of my compiler. I think it is "new enough".
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=c:/_data/cpp/mingw/bin/../libexec/gcc/x86_64-w64-mingw32/6.3.0/lto-wrapper.exe
Target: x86_64-w64-mingw32
Configured with: ../src/configure --enable-languages=c,c++ --build=x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --disable-multilib --prefix=/c/temp/gcc/dest --with-sysroot=/c/temp/gcc/dest --disable-libstdcxx-pch --disable-nls --disable-shared --disable-win32-registry --enable-checking=release --with-tune=haswell
Thread model: win32
gcc version 6.3.0 (GCC)
When I try to compile this program:
#include <boost/outcome.hpp>
int main() {}
g++ -std=c++14 -IC:\_data\cpp\boost.outcome-master\include -Wall test.cpp -o test.exe
In file included from C:\_data\cpp\boost.outcome-master\include/boost/outcome/outcome.hpp:26:0,
from C:\_data\cpp\boost.outcome-master\include/boost/outcome.hpp:1,
from test.cpp:1:
C:\_data\cpp\boost.outcome-master\include/boost/outcome/outcome_v1.0.hpp: In function 'char** backtrace_symbols(void* const*, size_t)':
C:\_data\cpp\boost.outcome-master\include/boost/outcome/outcome_v1.0.hpp:1356:34: error: 'memset' was not declared in this scope
memset(&ihl, 0, sizeof(ihl));
^
C:\_data\cpp\boost.outcome-master\include/boost/outcome/outcome_v1.0.hpp:1409:52: error: '_ui64toa_s' was not declared in this scope
_ui64toa_s((size_t) bt[n], p, end - p, 16);
^
C:\_data\cpp\boost.outcome-master\include/boost/outcome/outcome_v1.0.hpp:1410:26: error: 'strchr' was not declared in this scope
p = strchr(p, 0);
^
C:\_data\cpp\boost.outcome-master\include/boost/outcome/outcome_v1.0.hpp:1418:47: error: '_itoa_s' was not declared in this scope
_itoa_s(ihl.LineNumber, p, end - p, 10);
^
C:\_data\cpp\boost.outcome-master\include/boost/outcome/outcome_v1.0.hpp:1419:24: error: 'strchr' was not declared in this scope
p = strchr(p, 0) + 1;
^
make: *** [Makefile:2: main] Error 1
When I compile this program (with manually added headers):
#include <string.h>
#include <stdlib.h>
#include <boost/outcome.hpp>
int main() {}
I get this compiler output:
g++ -std=c++14 -IC:\_data\cpp\boost.outcome-master\include -Wall test.cpp -o test.exe
In file included from C:\_data\cpp\boost.outcome-master\include/boost/outcome/outcome.hpp:26:0,
from C:\_data\cpp\boost.outcome-master\include/boost/outcome.hpp:1,
from test.cpp:3:
C:\_data\cpp\boost.outcome-master\include/boost/outcome/outcome_v1.0.hpp: In function 'char** backtrace_symbols(void* const*, size_t)':
C:\_data\cpp\boost.outcome-master\include/boost/outcome/outcome_v1.0.hpp:1409:52: error: '_ui64toa_s' was not declared in this scope
_ui64toa_s((size_t) bt[n], p, end - p, 16);
^
C:\_data\cpp\boost.outcome-master\include/boost/outcome/outcome_v1.0.hpp:1418:47: error: '_itoa_s' was not declared in this scope
_itoa_s(ihl.LineNumber, p, end - p, 10);
^
make: *** [Makefile:2: main] Error 1
Is it me doing something wrong, or is it a bug?
Here's an inconsistency between the std
and your version.
#include <cstdlib>
#include <iostream>
#include <future>
#include <boost/outcome/future.hpp>
namespace lw = boost::outcome::lightweight_futures;
int main(int argc, char *argv[])
{
try
{
lw::promise<int> p;
//std::promise<int> p;
p.get_future();
p.set_value(1);
std::cout << "done\n";
}
catch (std::exception& e)
{
std::cout << e.what() << "\n";
}
return EXIT_SUCCESS;
}
The std
version prints done
, but the lw
version throws an exception no state
.
Is the inconsistency by design or is it a bug?
using namespace BOOST_OUTCOME_V1_NAMESPACE;
struct udt
{
// no default constructor
udt(int) {}
udt(const udt &) = default;
udt(udt &&) = default;
};
auto f = []() -> result<udt>
{
auto g = [] { return result<int>(5); };
/* This fails because BOOST_OUTCOME_TRYV() returns a result<void>
which if it were valued void, would implicitly convert into a
default constructed udt which is not possible, hence the compile error.
*/
BOOST_OUTCOME_TRYV(g());
return udt(5);
};
When fixing issue #12 last night, I undid a hack which had trivial copy/move constructors and assignment used when the type is trivially destructible. This allowed basic_monad to work in constexpr with types with trivial copy/move constructors and assignment, but it failed if the trivial types had non-trivial copy/move constructors which caused issue #12.
Right now value_storage uses one of four storage implementations:
Instead we probably need a hierarchy of storage implementations:
Under this new schema you would get:
value_storage_impl_tc_td
- trivially copyable, trivially destructiblevalue_storage_impl_ntc_td
- non-trivially copyable, trivially destructiblevalue_storage_impl_tc_ntd
- trivially copyable, non-trivially destructible (***)value_storage_impl_ntc_ntd
- non-trivially copyable, non-trivially destructibleIssues outstanding:
{
std::optional<std::vector<int>> o { std::in_place, { 18, 4 }, std::allocator<int> {} };
VERIFY( o );
VERIFY( o->size() == 2 );
VERIFY( (*o)[0] == 18 );
}
Add in check() functions for internal usage
http://ned14.github.io/boost.outcome/md_doc_md_03-tutorial_b.html#try_operation
it says
Unlike the try operator, the macro is not an expression so you can't write statements like if(BOOST_OUTCOME_TRY(var, expr)) as you can in Rust or Swift, this is due to a limitation of the C++ language (you can't return from functions in an expression).
However, I found this implementation of the TRY macro that seems to get around that issue: https://github.com/oktal/result
Need a unit test case exercising the Args&&...
Suggestions made:
basic_monad
-> outcome_base
or basic_outcome
monad_error
-> bad_outcome
or outcome_error
Two votes were for bad_outcome
, I do like the ring of it.
Motivating use case:
include(ExternalProject)
ExternalProject_Add(
outcome URL https://dedi4.nedprod.com/static/files/boost.outcome-v1.0-source-latest.tar.xz
CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND ""
)
add_executable(main main.cpp)
set_property(TARGET main PROPERTY CXX_STANDARD 14)
target_include_directories(main PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/outcome-prefix/src/outcome/include")
The following program crashes:
ned::promise<int> p;
auto t = p.get_future();
t.then([](ned::future<int> const&) {});
p.set_value(0);
The reason is: in future.hpp
line 771, it checks v.is_ready()
, and in monad.hpp
line 866, the return value is output_type()
, which is incorrectly "not ready", it should return output_type(value)
instead.
Also this overload:
As the CATCH_ALL macro confers no benefit, replace implementation with this API or replace entire macro.
Add FAQ entry on how the throw keyword is never elided by any compiler
Still to decide:
Fails to compile due to selecting copy assignment when udt does not provide one:
expected<udt> n(make_unexpected(std::error_code(ENOMEM, std::generic_category())));
n = make_unexpected(std::error_code(EINVAL, std::generic_category()));
Fix for this is blocked by issue #11
Current test/constexprs is so borked it's effectively useless. New script above Tom has fixed for me.
https://github.com/BoostGSoC17/static-map/tree/development/test
Notes from review item:
So, I would do something like we have in the documentation for
Boost.Optional.
The initial page is very short. Short description and a really small
example. In fact too small to sell the power of this library:
http://www.boost.org/doc/libs/1_64_0/libs/optional/doc/html/index.html
And then in a number of subsequent pages, we describe feature by feature
with short examples:
http://www.boost.org/doc/libs/1_64_0/libs/optional/doc/html/boost_optional/quick_start.html#boost_optional.quick_start.optional_return_values
http://www.boost.org/doc/libs/1_64_0/libs/optional/doc/html/boost_optional/quick_start/optional_automatic_variables.html
http://www.boost.org/doc/libs/1_64_0/libs/optional/doc/html/boost_optional/quick_start/optional_data_members.html
http://www.boost.org/doc/libs/1_64_0/libs/optional/doc/html/boost_optional/quick_start/bypassing_unnecessary_default_construction.html
http://www.boost.org/doc/libs/1_64_0/libs/optional/doc/html/boost_optional/quick_start/storage_in_containers.html
I would do the same for Outcome:
In the landing page just give this example:
https://github.com/akrzemi1/__sandbox__/blob/master/outcome_intro2.md
It only introduces outcome::expected
(lot of users will not have heard of
std::expected
) and the TRY operation to attract attention of more
informed users.
Then in the second page I would provide a number of short capters each with
one annotated example, each introducing one feature:
outcome
outcome
If you like this idea, I would volunteer to write up the initial pages.
Regards,
&rzej;
Also, the static assert on nothrow move is not predicated on if there is a move constructor, not with fallback onto a copy constructor.
The static assert on default constructibility of T is probably redundant.
Also spell out:
Currently it returns no_value_type
, not void
.
Consider the generic use case, for example:
template<class T>
inline T await_resume(future<T>& fut)
{
return fut.get();
}
Such code will fail to compile with future<void>
.
Both:
For static_checked_optional_outcome/static_checked_optional_result::
There's no make_ready_future
for future<void>
.
Besides, currently make_ready_future(t)
is implemented as future<T>(t)
, however, I'd suggest dropping such ctor for future<T>
, consider the case for future<void>
, there's no corresponding ctor that makes it a ready future, future<void>()
? no, the default constructed one is invalid. Such value-init ctor is confusing and inconsistent.
That would be Paul Bristow, in
The following fails to compile:
struct Date // no default constructor
{ // (no default date exists)
explicit Date(int) {}
};
out::expected<Date> fun ()
{
return Date{1}; // this fails to compile
}
It fires a static_assert
:
"value_type must be default constructible (LEWG Expected requirement)"
This is incorrect, as per p0323r1 (see section X.Z.4.1 in the proposed wording) is_default_constructible
is only required when someone triggers the default constructor of expected<T>
. Otherwise expected
would be not usable for any type without default constructor.
Additionally, .error() is supposed to return a reinterpret style reference to the error state, not by value.
Consider the following use case:
ned::promise<int> p;
auto t = p.get_future();
for (int i = 0; i != 65536; ++i)
t = t.then([](ned::future<int>&& t) { return t.get() + 1; });
p.set_value(0);
std::cout << "ans: " << t.get();
Every new t
depends on its previous result, and since the first t
is stalled, a long chain of continuation is constructed. The continuation is invoked when the result is set, as the result, the continuation chain is invoked in a tail recursion manner, and the depth in this example is big enough to cause stackoverflow.
The problem (stackoverflow) could be solved though, and I don't consider this a bug in this library, it's a design decision. It's ok that this library doesn't support such a use case and just document the limitation clearly.
What's the intended decision here?
Your documentation sometimes talks about the class extended_error_code
which does not exist. Instead, you probably mean error_code_extended
.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.