mnmlstc / core Goto Github PK
View Code? Open in Web Editor NEWC++14 (and beyond) library features implemented in C++11
Home Page: https://mnmlstc.github.io/core/
License: Other
C++14 (and beyond) library features implemented in C++11
Home Page: https://mnmlstc.github.io/core/
License: Other
As per the proposal, optional should support use as a constexpr
if T
can also be used as a constexpr
.
Reference implementations that support this:
Great library by the way, scratches so many itches for me
This would be a big add, but there's some good reasons why it's worth the effort
What's specified in the proposal looks quite doable. Maybe a version 2 feature?
Sidenote: It'd be extra cool if it didn't rely on as many heap allocations as boost (it creates a shared_ptr for each entry!). It might also be possible to avoid using a linked-list or at least optimize for the common case of only 1-2 handlers per signal. Signals almost always are fired far more often than slots are connected/disconnected and linked-lists do unspeakable things to your CPU's cache when you try and iterate through them. Chromium actually uses a plain old vector and assigns each connection a unique id. You have to brute force find/remove in order to disconnect signals but this is often still faster than using a linked list.
Let me know what you think! I'd be willing to create a prototype over the weekend if you're interested.
Dear Tres,
I found no other way to contacting you, so first of all: thanks for that wonderful library. Lightweight, small, no boost'ish depencies, and modern c++11 (sometimes too modern since we stick with gcc 4.7.3+ versions), but some of it still is working and extremly helpful in my daily business.
What I wanted to ask: current, string_view is a read-only type. Do you plan to make it mutable, so immutability would be decided on the constness of the instance (remark: I have used pj_str_t of pjsip.org for years, which is basically the same as the string_view, but mutable)?
Maybe the application is overlapping to the range concept, but modifying a string_view's underlying data would be a nice feature, hiding away the underlaying/owning data structure.
A second remark regarding string_view::find()
the std::basic_string exposes a
size_type
find(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPT;
whereas the string_view is basically missing the offset parameter __pos. Any plans to get compatible with this one?
BTW: what are you working on in 'real'-life? For PM: puls (at) x-fabric (single dot) com
Thanks and have a good day,
Roman
PS: we tried working with the variant class, but in practice, a single callstack in gdb can fill multiple screens with that approach. Maybe a .gdb printer may help here.
Implementing the proposed function abs_diff
in N4318 should be straightforward and simple, and would certainly be useful.
Test case:
#include <type_traits>
#include <core/functional.hpp>
struct A {};
struct B {};
struct C {};
typedef A(*foo)(B,C);
static_assert( std::is_same< core::function_traits<foo>::argument<0>, B >::value, "arg0 != B" );
static_assert( std::is_same< core::function_traits<foo>::argument<1>, C >::value, "arg1 != C" ); // fails
Tested on Apple clang-700.1.76 and Homebrew gcc 5.2.0 at OS X.
std::hash<std::string_view> on cppreference
Section 24.4.5 in C++ 17 working draft N4659: Hash support:
Note: The hash value of a string view object is equal to the hash value of the corresponding string object.
Currently the following tests fail and although it's not std::
string_view
, you might consider this for core::string_view
.
SECTION("hash-std::string") {
CHECK( std::hash<core::string_view>()("hello") == std::hash<std::string>()("hello") );
CHECK( std::hash<core::string_view>()("world") == std::hash<std::string>()("world") );
}
prompt> test-string-view.exe --reporter compact
string-view.cpp:383: failed: std::hash<core::string_view>()("hello") == std::hash<std::string>()("hello") for: 2191231550387646743 == 2762169579135187400
string-view.cpp:384: failed: std::hash<core::string_view>()("world") == std::hash<std::string>()("world") for: 5568329560871645431 == 8751027807033337960
Failed 1 test case, failed 2 assertions.
MNMLSTC Unittest was an experiment for unit testing libraries. It wasn't widely used outside of MNMLSTC libraries, and it is time to say farewell. If C++17 (or some technical specification) adds a way to pass the current line and file of an exception without the use of macros, MNMLSTC Unittest may move out of deprecation. However, until that time, MNMLSTC Core should use the Catch, due to its popularity and small size.
Additionally, the tests/CMakeLists.txt
file should handle the downloading and configuring of Catch for unit tests, should they be enabled. This will remove the requirement of having a unit test library installed on the machine, and simply require that an internet connection be available.
Author's Note:
I wrote MNMLSTC Unittest to see if it would be possible to have a unit test library in the style of
Python, and while it more or less worked, I unfortunately have to admit that having line numbers and
files in debug output is extremely useful in large projects. MNMLSTC Unittest was fun to write, but I
feel that Catch will make it easier for others to be involved and test changes or fixes to MNMLSTC
Core (and other MNMLSTC Libraries). I will admit that it was a good run, but there are a large
number of frankly superior unit test libraries that are able to interact with tools like Jenkins and
Hudson (or anything that reads JUnit XML). Additionally, MNMLSTC Unittest never played well with
CDash, despite relying entirely on CTest as its test runner. With all of the above issues stated, it was
only a matter of time until MNMLSTC Unittest was deprecated.
Hi,
When i try to instantiate core::result<T>
on types which are not default constructible, i run into a compiler error. As far as i see this requirement is not listed in the documentation. Looking at the source code, i find this:
result (::std::error_condition const& ec) :
valid { not ec }
{
if (*this) { ::new (::core::as_void(this->val)) value_type(); }
else { ::new (::core::as_void(this->cnd)) error_type(ec); }
}
So if someone uses an 'ok' error_condition in the result the underlying storage will be initialized with a default constructed instance of T. I see the underlying intent that since there is no error thus there should be a value, but this is also adding the default constructible requirement for type T, which i see a bit restrictive. Is there something that could be done, to use non default constructible types?
Thanks
Andras
This type is partially inspired by rust-lang's Result<T, E>
. Unlike rust-lang, however, result<T>
will be much like expected<T>
, except (heh) instead of an exception it will contain a std::error_condition
. This will allow for user defined conditions while also remaining portable.
It will have an interface equivalent to expected<T>
, minus exception related tasks. It follows in the footsteps of optional<T>
, for which no error is expressed. It is also safer to use for platforms where exceptions may not be entirely viable, such as the Playstation 4. An exception may be thrown in result<T>::value
where there is no value to use, however. (It will always be of type std::system_error
).
In reference to Issue #7, it will be easier to mark many swap function as noexcept
if these type traits are available. While clang does provide some of their own traits, these will not depend on compiler or library specific implementations.
This is a nice (and I believe completely safe) convenience:
#include <core/memory.hpp>
core::observer_ptr<int> foo(int *i) {
return i;
}
int main() {
int a = 0;
auto b = foo(&a);
}
but it currently fails:
ptr.cc: In function ‘core::v1::observer_ptr<int> foo(int*)’:
ptr.cc:4:12: error: could not convert ‘i’ from ‘int*’ to ‘core::v1::observer_ptr<int>’
return i;
Due to a bad habit, I have introduced undefined behavior by placing the swap functions for all types in MNMLSTC Core in the std
namespace. To resolve this, all types' must have a swap function in their local namespace (in this case core::v1
)
There are many parts of MNMLSTC Core that currently resolve to using the standard namespace without a full global resolution before hand (that is, std::
is used instead of ::std::
. It is considered good practice to fully resolve the standard library's namespace, and a pass to insure this should be done on all MNMLSTC Core components.
From core's documentation pages there seems to be no obvious link to core's project page to help the reader to obtain the code to actually use it. I'd expect such a link on the front page of the neat documentation site, or on an easy-to-spot page like Getting MNMLSTC Core, or Download MNMLSTC Core.
Search the docs for GitHub, source, or code from the documentation pages did not reveal a pointer to this project.
I know it was written before the proposal but is there any chance for bringing these two classes together into one and supporting the API from the proposal? Perhaps for V2?
Boost.Range provides a variety of functions that take a range type T
, and then call the c++ stdlib <algorithm>
header equivalent.
For example:
boost::for_each({1, 2, 3}, [](int x) { });
Will in turn call std::for_each
. There is, honestly, no reason that MNMLSTC Core cannot provide this same functionality.
Hi, are there any future releases planned? For our case, it'd be nice to have the fix to #23 without building from master.
Thank you!
Kevin
While some functions that would result in exceptions or usage of RTTI might not be called within a given project, a compiler will still attempt to generate code, and this can result in linker errors. There won't be a specific approach to detect whether or not a given compiler has exceptions enabled. Instead, the user will decide this during configuration, and use $<TARGET_PROPERTY:mnmlstc::core,INTERFACE_COMPILE_DEFINITIONS>
in a given build. I'm still hesitant on adding a configure.hpp header.
Of course, this means that certain types will be unavailable in these situations (specifically, expected<T>
)
Edit: 2015-JAN-30
The exceptions will be able to be disabled, however, RTTI is required for core::any
to work. The definitions will be available at configure time, or can be added manually. This will be documented as well. If RTTI is disabled, including <core/any.hpp>
will most likely result in the use of a #error
. A single member function in core::variant
will be disabled as well.
Revision 7 of the string_view proposal shows all the find* functions taking a position. Currently, core::string_view
does not do this, and it limits the interoperability with std::string
(as string_view is intended to be a drop-in API replacement for a std::string const&
)
Implementing these functions is necessary for compatibility with the proposal. HOWEVER, these functions cannot be constexpr due to limitations with C++11. As MNMLSTC Core does focus on targeting C++11, we have no way of implementing these where the non-constexpr case would be easily optimizable.
While there is a plan to eventually have a version of MNMLSTC Core targeting C++14 (MNMLSTC Core 2.0), that it outside the scope of the 1.2 release.
This is partially dependent on #14. The expected<T>
optional type is missing an extremely large feature set when compared to optional<T>
. It needs to have a variety of functions added (emplace, variadic constructors), as well as additional relational operator overloads.
Maybe a kitchen sink, while I'm at it.
We are using MNMLSTC core to provide polyfills for string_view
and optional
in the upcoming MongoDB C++11 driver: https://github.com/mongodb/mongo-cxx-driver/tree/master
It has been a big help for our GCC and clang builds, but unfortunately core doesn't appear to work on VS 2015. I just tried HEAD of master last night. If we can't use MNMLSTC core with VS 2015, then our options are to either build our own polyfills from scratch and use those everywhere, which we are not excited about, or to find a different source of the polyfills to use only with VS 2015, which we also aren't too excited about.
It does look like some CMake awareness of WIN32 was added recently. Is VS 2015 support on the roadmap for 2.0? I realize that VS 2015 is still a pretty flawed C++11 compiler, so perhaps it just isn't viable yet for something like core.
In any event, an answer either way would be helpful, and excited to see work progressing towards core 2.0.
Compiling the following code with clang 3.4.2 using libc++ on Linux fails:
struct Test1
{
Test1( int value ) {}
};
struct Test2
{
Test2( double value ) {}
};
core::variant<Test1, Test2> test{ Test2{ 0.0 } };
error:
libs/modules/mnmlstc-core/git/include/core/type_traits.hpp:86:47: error: no type named 'type' in 'std::__1::enable_if<false, void>'; 'enable_if' cannot be used to disable this declaration
using enable_if_t = typename ::std::enable_if<B, T>::type;
^
libs/modules/mnmlstc-core/git/include/core/variant.hpp:221:11: note: in instantiation of template type alias 'enable_if_t' requested here
class=enable_if_t<
^
test.hpp:141:29: note: in instantiation of template class 'core::v1::variant<Test1, Test2>' requested here
core::variant<Test1, Test2> test{ Test2{ 0.0 } };
Adding a default constructor to Test1 "fixes" the problem.
EOM
In order to resolve Issue #1, a constexpr forward and move equivalent are necessary. Additionally, internals of MNMLSTC Core should rely on these functions.
When building libbsoncxx against core HEAD with -Wall, I'm getting lots of warnings about the use of the clang::fallthrough
attribute in the new string_view header:
src/bsoncxx/third_party/EP_mnmlstc_core-prefix/src/EP_mnmlstc_core/include/core/string_view.hpp:100:55: warning: attributes at the beginning of statement are ignored [-Wattributes]
case 2: hash ^= ::std::uint64_t(data[1]) << 8; [[clang::fallthrough]];
Easy enough to work around by adding -Wno-attribute but that is not ideal.
The function objects such as std::equal_to
, or std::plus
are not constexpr in C++11. To insure that everyone using C++11 still has this capability, these should be added, along with the function_object<void>
specializations. The recently added type traits may also come in handy.
Now that #1 has been closed, and a constexpr move
and forward
function were added to the utility component, the core::invoke
function and its overloads can be set to be constexpr.
The only limitation is that the unpack versions of core::invoke
will not be constexpr, due to limitations with std::get
, std::tuple
, friends.
Hello,
this is a bug in any
/ dispatch
.
Types that are not noexcept copy constructable are treated by dispatch
as not small, but their value is stored in the pointer of any
like a small type. When applying any_cast
to such an any
instance a SEGV occurs as the value is interpreted as the address to the value.
Please see the following test case:
TEST_CASE("small-assignment", "[assignment]") {
struct Foo {
int f_;
Foo()
: f_(0) {
}
Foo(const Foo& other)
: f_(other.f_) {
}
Foo(Foo&& other) {
swap(*this, other);
}
Foo& operator=(Foo other) {
swap(*this, other);
return *this;
}
void swap(Foo& first, Foo& second) {
if(&first != &second) {
using std::swap;
swap(first.f_, second.f_);
}
}
};
// not small because not noexcept
CHECK_FALSE(::core::impl::is_small<Foo>::value);
int f = 42;
Foo foo;
foo.f_ = f;
CHECK(f == foo.f_);
core::any a = foo;
CHECK(f == foo.f_);
CHECK(f == core::any_cast<Foo>(a).f_); // Seg fault - the address (this) of
// the temporary object has a value of
// 0x2A (42)
core::any b = a;
CHECK(f == foo.f_);
CHECK(f == core::any_cast<Foo>(a).f_);
CHECK(f == core::any_cast<Foo>(b).f_);
core::any c = std::move(a);
CHECK(f == foo.f_);
CHECK(0 == core::any_cast<Foo>(a).f_);
CHECK(f == core::any_cast<Foo>(b).f_);
CHECK(f == core::any_cast<Foo>(c).f_);
}
An implementation of N4315 should be added.
Boost.Range provides several functions to simplify the C++ stdlib's <numeric>
functions.
There is no reason that MNLSTC Core cannot provide this same feature set.
static void clone (data_type const& source, data_type& data) {
allocator_type alloc { };
auto const& value = *static_cast<Type* const>(source);
auto pointer = allocator_traits::allocate(alloc, 1);
allocator_traits::construct(alloc, pointer, value);
data = pointer;
}
If the construction throws, the allocated memory is leaked. The best way (I've seen) to work around this issues is to store the allocated memory in a unique_ptr with a custom dtor that simply calls allocator::deallocate.
For reference here is how I solved this problem in my any implementation (Which is based off of libc++'s std::function).
storage_base* copy() const
{
using NewAlloc = typename Alloc::template rebind<storage_type>::other;
NewAlloc a(m_pair.second());
using Dtor = allocator_destructor<NewAlloc>;
std::unique_ptr<storage_type, Dtor> tmp(a.allocate(1), Dtor(a, 1));
::new ((void*)tmp.get()) storage_type(
m_pair.first(), Alloc(a)
);
return tmp.release();
}
The header dependency route in MNMLSTC Core is a bit unclean at the moment. For instance, the utility component does not include the type traits component, even though it would greatly benefit from it. A small pass to clean up these headers is required. While I originally was against all components of MNMSLTC Core depending on the type traits component, it seems as though this is inevitable due to how useful it is.
Hello Izzy!! :D
core::v2::any
issues a compiler error when the constructor for a parameter of constant pointer type is used. This can be reproduced by attempting to wrap a pointer to a const int
:
const int x = 5;
core::v2::any container(&x);
reinterpret_cast from 'core::v2::impl::data_type*' (aka void**) to 'core::v2::impl::dispatch<const MyType*, true>' (aka const MyType**) casts away qualifiers.
I'm using Clang on a slightly outdated Xcode and using this library to aid in compatibility with old versions of Mac OS X.
According to http://vtk.org/Wiki/CMake:How_To_Find_Libraries
I would expect find_package(core 1.1.0) to provide variables core_FOUND, core_VERSION, core_INCLUDE_DIRS, but instead it gives core_FOUND, core_VERSION (and CORE_VERSION), and CORE_INCLUDE_DIR (not plural).
There are quite a few type traits in the standard that are missing here. Here's a reference implementation I've been using in personal projects (pretty much copy and pasted from the standard proposal)
I was going to submit a pull request with these added but I notice you've implemented your own versions of common_type
and a few other traits. Is there a reason for this? Both libc++ and libstd++ support it
With the boost proposal of an expected<T, U>
it would make sense to make an either<T, U>
that performs the same functionality that it would in other languages. The reason for this over using a variant as an alias is:
either<T, U>
would be a smaller type (no integer to tell which is which)result<T>
and expected<T>
could be turned into template aliases (in a future major release. This can't be done now, as this would break compatibility, which would in turn break the promise of semantic versioning. It's happened only once before (moving the expected<T>
into the core/optional.hpp
header) and I would prefer to not do it again.Additionally, naming a type that is either A or B expected<T, U>
is probably not the best idea. Honestly one would expect either T or U. Not expect either T or U.
Commit 5a0157b removes ::empty()
method from from meta::list
and brakes this function.
It isn't listed in documentation but i think highly useful and resembles std::get introduced for C++14 tuples.
unsafe_any_cast
is considered to be a much faster use of any_cast
and some arguments have been given that it should be in the Library Fundamentals TS. Additionally, both Boost.Any and the Adobe any implementation provide an unsafe_any_cast
.
While I am definitely against the introduction of potential undefined behavior (which is more than possible with unsafe_any_cast
), the potential performance benefits as well as interop with other any implementations is more than worth it.
As of release 1.0, MNMLSTC Core had 2 optional types, core::optional<T>
and core::expected<T>
. With 1.1 MNMLSTC Core will gain a third optional type, core::result<T>
(mentioned in issue #13). It is most likely a good idea to move both expected<T>
and result<T>
into the optional component. This would make the in_place_t
type available, allowing for all optional types to be constructed with a variadic number of arguments.
This will break the semantic versioning, however hopefully no one has tried to actually use the expected<T>
for a very critical app yet, because it is woefully lacking in features when compared to core::optional<T>
.
I was unable to find a revision of the string_view
proposal past revision 7, but the text for max_size
in rev 7 is as follows:
constexpr size_type max_size() const noexcept
Returns: The largest possible number of char-like objects that can be referred to by a basic_string_view.
This implementation currently only returns the size of the current string view which is different from the standard library implementation provided on my machine (Apple LLVM version 7.0.2 (clang-700.1.81)
).
I believe it should return ::std::numeric_limits::<size_type>::max()
instead.
It would be nice to have 'get' as member function of the variant template, instead of using core::get(...). If I understood the documentation for 'auto get() noexcept' correctly, it implies that is should actually be a member function:
Depending on the value of *this (reference, const reference, rvalue) the type of the value returned will be affected as well.
As optional types are effectively variants (pedantically speaking they're not, but they are, but they're not), there is no reason why a match function for all optional types should not be provided. This should be both a member function, as well as an ADL-capable function within the core::v1
namespace. This would allow for stuff like:
optional<int> f { 4 };
f.match(
[] (int x) { /* do something here */ },
[] (nullopt_t) { /* do something else here */ }
);
Scope guards would be much more useful if they allowed easy dismissal. This is a part of what is generally recognized as the scope guard idiom. Makes for easy support for "rollback" functionality (see the article below on why this is nicer than try/catch). Plus it would solve issue #16 :)
Reference:
#include <core/string.hpp>
int main() {
const std::string a = "a";
const std::string b = "b";
core::string_view bv{b};
return a == bv;
}
This fails to compile because:
compare.cc:8:14: error: no match for ‘operator==’ (operand types are ‘const string {aka const std::basic_string<char>}’ and ‘core::v1::string_view {aka core::v1::basic_string_view<char>}’)
It works with boost string_ref http://www.boost.org/doc/libs/1_55_0/libs/utility/doc/html/string_ref.html
N4017 discusses several non-member functions to act on several container types. These are most definitely useful and extremely easy to add and implement.
core::variant<Ts...>
does not currently support using a get function via a given type. This turns out to be easier to implement than one might think. As a result, there is no reason to NOT permit this kind of usage. Adding this feature will also give better interop with Boost.Variant.
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.