Git Product home page Git Product logo

cmcstl2's People

Contributors

antonbikineev avatar beman avatar caseycarter avatar cjdb avatar ericniebler avatar jicama avatar johelegp avatar jwakely avatar tcbrindle avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cmcstl2's Issues

Future work: WeakRange

template <class S, class I>
concept WeakSentinel =
  WeakIterator<I>() && Semiregular<S>() &&
  requires (const I& i, const S& s) {
    { i == s } -> Boolean;
    { i != s } -> Boolean;
    // Axiom: bool(i != s) == !bool(i == s)
  };

template <class R>
  requires WeakIterator<decltype(begin(declval<remove_reference_t<R>&>()))>()
using IteratorType = decltype(begin(declval<remove_reference_t<R>&>()));

template <class R>
  requires WeakSentinel<decltype(end(declval<remove_reference_t<R>&>())), IteratorType<R>>
using SentinelType = decltype(end(declval<remove_reference_t<R>&>()));

template <class R>
concept bool WeakRange =
  requires { typename SentinelType<R>; };

template <class R>
concept bool WeakInputRange =
  WeakRange<R> && WeakInputIterator<IteratorType<R>>();

template <class R, class T>
concept bool WeakOutputRange =
  WeakRange<R> && WeakOutputIterator<IteratorType<R>, T>();

template <class R>
concept bool Range =
  WeakRange<R> && Sentinel<SentinelType<R>, IteratorType<R>>();

I postulate that there is no model of InputIterator / OutputIterator that is not equivalent to some model of WeakInputIterator / WeakOutputIterator, i.e, InputIterator and OutputIterator are extraneous and do not increase the expressiveness of the design. If we relax every Input/Output Range/Iterator requirement to Weak Input/Output Range/Iteratator the Input/Output Iterator concepts could be deprecated.

type-erased any_input_iterator

I'll just leave this here. Caveat: largely untested and probably buggy as hell.

//  Copyright Eric Niebler 2016
//
//  Use, modification and distribution is subject to the
//  Boost Software License, Version 1.0. (See accompanying
//  file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
namespace any_iterator_detail
{
	enum class op { copy, move, nuke, bump, comp };	

	struct counted
	{
		std::atomic<long> cnt{ 1 };
	};
	ranges::InputIterator{I}
	struct shared_iterator : counted
	{
		shared_iterator(I i) : it(std::move(i)) {}
		I it;
	};

	union blob
	{
		counted* big;
		std::aligned_storage<2 * sizeof(void*)>::type tiny;	
	};	

	template <typename It>	
	using is_small =
	    std::integral_constant<bool, (sizeof(It) <= sizeof(blob::tiny))>;
	using small_tag = std::true_type;	
	using big_tag = std::false_type;

	inline bool uninit_noop(op, blob*, blob*)
	{
		return false;	
	}

	template<typename Reference>
	[[noreturn]] inline Reference uninit_deref(blob const &)
	{
		std::terminate();
	}	

	template <typename Reference, ranges::InputIterator I>
	static Reference deref_small(blob const & p)
	{
		return **static_cast<I const *>(static_cast<void const *>(&p.tiny));
	}
		
	template <typename Reference, ranges::InputIterator I>
	static Reference deref_big(blob const& p)
	{	
		return *static_cast<shared_iterator<I> const *>(p.big)->it;
	}	

	ranges::InputIterator{I}	
	bool exec_small(op o, blob* src, blob* dst)
	{	
		switch (o)
		{
		case op::copy:
			::new (static_cast<void*>(&dst->tiny))
				I(*static_cast<I const *>(static_cast<void*>(&src->tiny)));
			break;
		case op::move:
			::new (static_cast<void*>(&dst->tiny))
				I(std::move(*static_cast<I*>(static_cast<void*>(&src->tiny))));	
			// fallthrough
		case op::nuke:
			static_cast<I*>(static_cast<void*>(&src->tiny))->~I();	
			break;	
		case op::bump:
			++*static_cast<I*>(static_cast<void*>(&src->tiny));
			break;
		case op::comp:
			return *static_cast<I const *>(static_cast<void*>(&src->tiny))
			    == *static_cast<I const *>(static_cast<void*>(&dst->tiny));
		}	
		return false;	
	}	
		
	ranges::InputIterator{I}	
	bool exec_big(op o, blob* src, blob* dst)
	{
		switch (o)
		{
		case op::copy:
			++(dst->big = src->big)->cnt;
			break;
		case op::move:
			dst->big = std::exchange(src->big, nullptr);
			break;
		case op::nuke:
			if (0 == --src->big->cnt)
				delete static_cast<shared_iterator<I>*>(src->big);
			break;
		case op::bump:
			++static_cast<shared_iterator<I>*>(src->big)->it;
			break;
		case op::comp:
			return static_cast<shared_iterator<I> const *>(src->big)->it
			    == static_cast<shared_iterator<I> const *>(dst->big)->it;
		}
		return true;	
	}	

	template<class Reference, class ValueType>
	struct any_input_cursor
	{
	private:
		blob data_ = { nullptr };
		Reference (*deref_)(blob const &) = &uninit_deref<Reference>;
		bool (*exec_)(op, blob*, blob*) = &uninit_noop;

		ranges::InputIterator{I} any_input_cursor(I i, small_tag)
		{
			::new (static_cast<void*>(&data_.tiny)) I(std::move(i));
			deref_ = &deref_small<Reference, I>;
			exec_ = &exec_small<I>;
		}
		ranges::InputIterator{I} any_input_cursor(I i, big_tag)
		{
			data_.big = new shared_iterator<I>(std::move(i));
			deref_ = &deref_big<Reference, I>;
			exec_ = &exec_big<I>;
		}
	public:
		using value_type = ValueType;
		using single_pass = std::true_type;
		any_input_cursor() = default;
		ranges::InputIterator{I} any_input_cursor(I i)
			requires ranges::ConvertibleTo<ranges::reference_t<I>, Reference>()
		: any_input_cursor(std::move(i), is_small<I>{}) {}
		any_input_cursor(any_input_cursor &&that)
		{
			that.exec_(op::move, &that.data_, &data_);
			ranges::swap(deref_, that.deref_);
			ranges::swap(exec_, that.exec_);
		}
		any_input_cursor(any_input_cursor const &that)
		{
			that.exec_(op::copy, const_cast<blob*>(&that.data_), &data_);
			deref_ = that.deref_;
			exec_ = that.exec_;
		}
		any_input_cursor& operator=(any_input_cursor &&that)
		{
			if (&that != this)
			{
				this->~any_input_cursor();
				::new (static_cast<void*>(this))
					any_input_cursor(std::move(that));
			}
			return *this;
		}
		any_input_cursor& operator=(any_input_cursor const &that)
		{
			if (&that != this)
			{
				this->~any_input_cursor();
				::new (static_cast<void*>(this)) any_input_cursor(that);
			}
			return *this;
		}
		~any_input_cursor()
		{
			exec_(op::nuke, &data_, nullptr);
		}
		Reference read() const
		{
			return deref_(data_);
		}
		bool equal(any_input_cursor const &that) const
		{
			return exec_(op::comp, const_cast<blob*>(&data_),
				const_cast<blob*>(&that.data_));
		}
		void next()
		{
			exec_(op::bump, &data_, nullptr);
		}
	};
}

template<class Reference, class ValueType =
	std::remove_cv_t<std::remove_reference_t<Reference>>>
using any_input_iterator =
	ranges::basic_iterator<
		any_iterator_detail::any_input_cursor<Reference, ValueType>>;

Re-tighten constraints on algorithms

...to not require the relaxation specified in [algorithm.general]/12:

Despite that the algorithm declarations nominally accept parameters by value, it is unspecified when and if the argument expressions are used to initialize the actual parameters except that any such initialization shall be sequenced before (ISO/IEC 14882:2014 §1.9) the algorithm returns.

which will be removed by the PR for ericniebler/stl2#261. Already done for the algorithms with overloads in Annex A.2 (equal, is_permutation, mismatch, swap_ranges, transform) by b160823.

test iterators

augment the iterators in test_iterators.hpp with configurable equality comparison (for input and output) and configurable proxy/non-proxy reference capability.

Once that's done, add some tests for iter_move and iter_swap of the iterator adaptors implemented in 8bda2c3.

Namespacing

The number of occurrences of qualified names is increasing, algorithms will make it grow like wildfire. Relocate everything into std::experimental::ranges_v1 sooner rather than later. Better: make the top-level namespace configurable so we can co-exist with a vendor implementation of the TS.

missing include in test/iterator/common_iterator.cpp

The "" header has been changed to reduce the number of other headers it includes:
http://gcc.gnu.org/gcc-6/porting_to.html

std::accumulate needs .

diff --git a/test/iterator/common_iterator.cpp b/test/iterator/common_iterator.cpp
index 3fc19e456246..715a3a953093 100644
--- a/test/iterator/common_iterator.cpp
+++ b/test/iterator/common_iterator.cpp
@@ -10,6 +10,7 @@
 // Project home: https://github.com/caseycarter/cmcstl2
 //
 #include <algorithm>
+#include <numeric>
 #include <stl2/iterator.hpp>
 #include "../simple_test.hpp"
 #include "../test_iterators.hpp"

Range concepts

Merge the range concepts and primitive operations into iterator.hpp as specified in the proposal.

Eradicate ext::Addressable

There's really no point now that std::addressof will be constexpr in C++17. Users should instead require _Is<is_object> and replace &foo with detail::addressof(foo) from detail/memory/addresof.hpp which is as constexpr as possible.

`decltype(__stl2::rend(declval<T&>()))` manifests as an error when T == forward_list<int>, but `decltype(__stl2::rbegin(declval<T&>()))` does not

Toying around with some container stuff, so I've defined these:

template <class T>
using reverse_iterator_t =  decltype(__stl2::rbegin(declval<T&>()));

template <class T>
using reverse_sentinel_t =  decltype(__stl2::rend(declval<T&>()));

template <class X>
concept bool ReversibleContainer() {
   return Container<X>() &&
      BidirectionalRange<X>() &&
      requires(X x, const X cx) {
         typename reverse_iterator_t<X>; // works
         typename reverse_sentinel_t<X>; // fails when X = forward_list<int>
         typename const_reverse_iterator_t<X>; // works
   };
}

Interestingly, reverse_iterator_t works, but reverse_sentinel_t causes the attached diagnostic.

Is there any particular reason why reverse_iterator_t<foward_list<int>> doesn't manifest as an error, but reverse_sentinel_t<forward_list<int>> does?

Remove deprecated functions

The following functions have deprecated overloads:

  1. equal
  2. is_permutation
  3. mismatch
  4. swap_ranges
  5. transform
  6. range/access.hpp

Dereferenceable

Consider adding Movable and DefaultConstructible requirements to Dereferenceable, since Readable and MoveWritable both now require them.

Compiler doesn't see subsumption of iterator concepts

#include <stl2/iterator.hpp>

template <stl2::InputIterator>
constexpr bool f() { return false; }
template <stl2::ForwardIterator>
constexpr bool f() { return true; }

int main() {
    static_assert(f<int*>());
}

error: call of overloaded ‘f()’ is ambiguous

constexpr extensions

Conforming implementations are not allowed to add constexpr to functions whose specification does not require it; the constexpr extensions in the library need a configuration toggle.

Disabled tests

Tests in alg.find_end, alg.mismatch, and alg.equal OOM the compiler.

std::foo_algorithm is more specialized than ranges::foo_algorithm

The calls to three-argument equal with an argument that has std as an associated namespace need explicit qualification to disambiguate, e.g., Line 219:

CHECK(stl2::equal(make_range(input_iterator<const int*>(ia),
                             sentinel<const int*>(ia+s)),
                  make_range(input_iterator<const int*>(ia),
                             sentinel<const int*>(ia + s)),
                  std::equal_to<int>()));

The stl2 overloads of equal are obviously more-constrained. Determine why the std overloads are being selected by overload resolution, and develop a plan to correct the problem.

ranges::less, etc. and Callable

Currently unable to pass less<T>{} to a function or class that takes a Callable parameter. Am I missing something in this example?

void lt(Callable f)
{
   cout << f(1, 2) << '\n';
} 

int main()
{
   lt(ranges::less<int>{});
}

Value semantics of Callables

For a callable F, the Callable concepts require Function<FunctionType<F>, /* ... */>(), so FunctionType<F> indirectly must satisfy CopyConstructible. Given that FunctionType<F> is very often a reference type, and CopyConstructible does not intentionally admit reference types, this is a mess.

The specifications of the algorithms otherwise ignore the value semantics (destruction, copy, move) of callables. Library functions accept them as value parameters, so they must at least satisfy Destructible. Library functions forward them to other library functions that accept them as value parameters, so they must at least satisfy MoveConstructible. Should they be CopyConstructible? The question boils down to whether or not we want a library function implementation to be able to pass callables to multiple other library functions in "raw" form or if it must first cook them with as_function. E.g., given:

template <InputIterator I, Sentinel<I> S, class Pred, class Proj>
  requires IndirectRegularCallable<Pred, Projected<I, Proj>>()
I foo_helper1(I, S, Pred, Proj);

template <InputIterator I, Sentinel<I> S, class Pred, class Proj>
  requires IndirectRegularCallable<Pred, Projected<I, Proj>>()
I foo_helper2(I, S, Pred, Proj);

template <InputIterator I, Sentinel<I> S, class Pred, class Proj>
  requires IndirectRegularCallable<Pred, Projected<I, Proj>>()
I foo(I i, S s, Pred pred, Proj proj);

can I implement foo as:

return foo_helper2(foo_helper1(i, s, pred, proj), s, pred, proj);

Or must I instead write:

auto&& pred_ = as_function(pred);
auto&& proj_ = as_function(proj);
return foo_helper2(foo_helper1(i, s, pred_, proj_), s, pred_, proj_);

For the time being, I think it's best to err on the side of the most stringent requirements - allowing the most freedom for algorithm implementations - and require callables to satisfy CopyConstructible. STL1 requires predicates to be CopyConstructible, so this is not a breaking change in any case.

Update the STL containers

What is the status on updating the STL containers to use concepts (and ranges) as well?

Have there been any discussions about this?

test/detail/temporary_vector.cpp:28:5: error: static assertion failed

With gcc trunk:

build % CXXFLAGS="-O3" cmake -DCMAKE_CXX_COMPILER=/var/tmp/gcc_test/usr/local/bin/g++ ..
build % make
...

/var/tmp/cmcstl2/test/detail/temporary_vector.cpp: In function ‘int main()’:
/var/tmp/cmcstl2/test/detail/temporary_vector.cpp:27:31: warning: requested alignment 256 is larger than 128 [-Wattributes]
     struct alignas(alignment) foo { char c; };
                               ^

/var/tmp/cmcstl2/test/detail/temporary_vector.cpp:28:5: error: static assertion failed
     static_assert(alignof(foo) == alignment);
     ^

test/detail/CMakeFiles/temporary_vector.dir/build.make:62: recipe for target 'test/detail/CMakeFiles/temporary_vector.dir/temporary_vector.cpp.o' failed
make[2]: *** [test/detail/CMakeFiles/temporary_vector.dir/temporary_vector.cpp.o] Error 1
CMakeFiles/Makefile2:1631: recipe for target 'test/detail/CMakeFiles/temporary_vector.dir/all' failed
make[1]: *** [test/detail/CMakeFiles/temporary_vector.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....

test/iterator/any_iterator and GCC 7

There is some issue with inheriting constructors. It would be nice to know if any of our proposed interfaces are running afoul of recent language changes.

Test coverage for `basic_iterator`

...is lacking now that many of the iterators are hand-coded. Dig out the prior basic_iterator implementations and use them as test cases in test/utility/basic_iterator.cpp.

missing include in test/iterator/common_iterator.cpp

The algorithm header has been changed to reduce the number of other headers it includes:
http://gcc.gnu.org/gcc-6/porting_to.html

std::accumulate needs numeric.

diff --git a/test/iterator/common_iterator.cpp b/test/iterator/common_iterator.cpp
index 3fc19e456246..715a3a953093 100644
--- a/test/iterator/common_iterator.cpp
+++ b/test/iterator/common_iterator.cpp
@@ -10,6 +10,7 @@
 // Project home: https://github.com/caseycarter/cmcstl2
 //
 #include <algorithm>
+#include <numeric>
 #include <stl2/iterator.hpp>
 #include "../simple_test.hpp"
 #include "../test_iterators.hpp"

less<> et al

...should be constrained in accordance with the results of ericniebler/stl2#152. The current constraints are only equivalent on an implementation whose < provides a total ordering for pointer values.

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.