GithubHelp home page GithubHelp logo

ryanhaining / cppitertools Goto Github PK

View Code? Open in Web Editor NEW
1.3K 1.3K 115.0 1.67 MB

Implementation of python itertools and builtin iteration functions for C++17

Home Page: https://twitter.com/cppitertools

License: BSD 2-Clause "Simplified" License

C++ 97.30% Python 0.88% Shell 0.21% CMake 0.85% Starlark 0.76%

cppitertools's People

Contributors

aaronjosephs avatar anirul avatar benjones avatar dmckeone avatar frboyer avatar grimreaper avatar jared-schmitz avatar jkhoogland avatar kc9jud avatar maxmarsc avatar mbradac avatar mbrukman avatar nvander1 avatar pnacht avatar reach2sayan avatar ryanhaining avatar ssbotelh avatar strega-nil 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  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

cppitertools's Issues

Can I get just the counts from combinations_with_replacement ?

I am interested in using this library to iterate over all "n multichoose k" possibilities for a multiset, but I am representing each set as a simple vector of counts, with length n, where all counts add up to k. Is it possible to extract the counts from your iterators without iterating through each "multiset" itself? I had a peek at the headers but I am a bit lost as to how its working exactly.

So using the provided example for combinations_with_replacement, I would like to get a simple result that would look like:

combinations_with_replacement({1, 2}, 4):
{ 4 0 }
{ 3 1 }
{ 2 2 }
{ 1 3 }
{ 0 4 }

Product begin won't compile

I was able to get the begin iterator for range to work:

auto r = iter::range(5);
auto first = r.begin();

But I can't get product to compile:

std::string s = "abc";
auto p = iter::product(s,s);
auto first = p.begin();

This was compiled on Visual Studio 2017.
Here's the error message:

1>main.cpp
1>d:\visual studio 2017\itertools_test\cppitertools\internal\iterbase.hpp(75): error C2672: 'iter::impl::get_iters::get_begin': no matching overloaded function found
1>d:\visual studio 2017\itertools_test\cppitertools\internal\iterbase.hpp(85): note: see reference to alias template instantiation 'iterator_type' being compiled
1>d:\visual studio 2017\itertools_test\cppitertools\product.hpp(39): note: see reference to alias template instantiation 'iterator_deref' being compiled
1>d:\visual studio 2017\itertools_test\cppitertools\product.hpp(54): note: see reference to alias template instantiation 'ProdIterDeref<std::basic_string<char,std::char_traits,std::allocator>&>' being compiled
1>d:\visual studio 2017\itertools_test\product_test\product_test\main.cpp(18): note: see reference to class template instantiation 'iter::impl::Productor<std::string &,std::string &>::IteratorTempl<Container,iter::impl::Productor<std::string &>::IteratorTempl<Container,iter::impl::Productor<>::Iterator>>' being compiled
1> with
1> [
1> Container=std::string &
1> ]
1>d:\visual studio 2017\itertools_test\cppitertools\internal\iterbase.hpp(75): error C2893: Failed to specialize function template 'unknown-type iter::impl::get_iters::get_begin(T &)'
1>d:\visual studio 2017\itertools_test\cppitertools\internal\iterbase.hpp(75): note: With the following template arguments:
1>d:\visual studio 2017\itertools_test\cppitertools\internal\iterbase.hpp(75): note: 'T=add_rvalue_reference<_Ty>::type'
1>d:\visual studio 2017\itertools_test\cppitertools\internal\iterbase.hpp(85): error C2672: 'std::declval': no matching overloaded function found
1>d:\visual studio 2017\itertools_test\cppitertools\internal\iterbase.hpp(85): error C2893: Failed to specialize function template 'add_rvalue_reference<_Ty>::type std::declval(void) noexcept'
1>d:\visual studio 2017\itertools_test\cppitertools\internal\iterbase.hpp(85): note: With the following template arguments:
1>d:\visual studio 2017\itertools_test\cppitertools\internal\iterbase.hpp(85): note: '_Ty=unknown-type &'
1>d:\visual studio 2017\itertools_test\cppitertools\product.hpp(39): error C3546: '...': there are no parameter packs available to expand
1>d:\visual studio 2017\itertools_test\cppitertools\product.hpp(54): error C3203: 'tuple': unspecialized class template can't be used as a template argument for template parameter '_Ty', expected a real type
1>d:\visual studio 2017\itertools_test\cppitertools\product.hpp(58): error C2512: 'std::is_same<unknown-type,unknown-type>': no appropriate default constructor available
1>d:\visual studio 2017\itertools_test\cppitertools\product.hpp(58): note: The target type has no constructors
1>d:\visual studio 2017\itertools_test\cppitertools\product.hpp(108): error C3203: 'tuple': unspecialized class template can't be used as a template argument for template parameter 'T', expected a real type

compilation of test code on OSX

Hi,
I tried to build the test code on OSX,
but a lot of the builds, which include functional.h fail with the error below.
I have not found a way to fix this yet, but if you have any suggestions where to start it would be appreciated.
Regards
Jiri

System:
$  uname -a
Darwin JiriMBP.home 14.4.0 Darwin Kernel Version 14.4.0: Thu May 28 11:35:04 PDT 2015; root:xnu-2782.30.5~1/RELEASE_X86_64 x86_64 i386 MacBookPro11,2 Darwin
$  g++ --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
Target: x86_64-apple-darwin14.4.0
Thread model: posix
c++ -o test_combinations.o -c -g -Wall -Wextra -std=c++11 -fdiagnostics-color=always -I/usr/local/include -I. -I/Users/Jiri/Documents/lib/cpp/iter/cppitertools test_combinations.cpp
In file included from test_combinations.cpp:1:
In file included from ./helpers.hpp:4:
In file included from /Users/Jiri/Documents/lib/cpp/iter/cppitertools/iterbase.hpp:13:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/functional:477:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1645:31: error: no matching constructor for
      initialization of 'std::__1::vector<char, std::__1::allocator<char> >'
            ::new((void*)__p) _Up(_VSTD::forward<_Args>(__args)...);
                              ^   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1572:18: note: in instantiation of function
      template specialization 'std::__1::allocator<std::__1::vector<char, std::__1::allocator<char> > >::construct<std::__1::vector<char,
      std::__1::allocator<char> >, iter::IteratorIterator<std::__1::__wrap_iter<std::__1::__wrap_iter<char *> *>, long>,
      iter::IteratorIterator<std::__1::__wrap_iter<std::__1::__wrap_iter<char *> *>, long> >' requested here
            {__a.construct(__p, _VSTD::forward<_Args>(__args)...);}
                 ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1453:14: note: in instantiation of function
      template specialization 'std::__1::allocator_traits<std::__1::allocator<std::__1::vector<char, std::__1::allocator<char> > >
      >::__construct<std::__1::vector<char, std::__1::allocator<char> >, iter::IteratorIterator<std::__1::__wrap_iter<std::__1::__wrap_iter<char *> *>, long>,
      iter::IteratorIterator<std::__1::__wrap_iter<std::__1::__wrap_iter<char *> *>, long> >' requested here
            {__construct(__has_construct<allocator_type, pointer, _Args...>(),
             ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:1633:25: note: in instantiation of function
      template specialization 'std::__1::allocator_traits<std::__1::allocator<std::__1::vector<char, std::__1::allocator<char> > >
      >::construct<std::__1::vector<char, std::__1::allocator<char> >, iter::IteratorIterator<std::__1::__wrap_iter<std::__1::__wrap_iter<char *> *>, long>,
      iter::IteratorIterator<std::__1::__wrap_iter<std::__1::__wrap_iter<char *> *>, long> >' requested here
        __alloc_traits::construct(this->__alloc(),
                        ^
test_combinations.cpp:21:12: note: in instantiation of function template specialization 'std::__1::vector<std::__1::vector<char, std::__1::allocator<char> >,
      std::__1::allocator<std::__1::vector<char, std::__1::allocator<char> > >
      >::emplace_back<iter::IteratorIterator<std::__1::__wrap_iter<std::__1::__wrap_iter<char *> *>, long>,
      iter::IteratorIterator<std::__1::__wrap_iter<std::__1::__wrap_iter<char *> *>, long> >' requested here
        sc.emplace_back(std::begin(v), std::end(v));
           ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:521:5: note: candidate constructor not viable:
      no known conversion from 'iter::IteratorIterator<std::__1::__wrap_iter<std::__1::__wrap_iter<char *> *>, long>' to 'size_type' (aka 'unsigned long') for
      1st argument
    vector(size_type __n, const_reference __x);
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:555:5: note: candidate constructor not viable:
      no known conversion from 'iter::IteratorIterator<std::__1::__wrap_iter<std::__1::__wrap_iter<char *> *>, long>' to 'initializer_list<value_type>' for 1st
      argument
    vector(initializer_list<value_type> __il, const allocator_type& __a);
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:566:5: note: candidate constructor not viable:
      no known conversion from 'iter::IteratorIterator<std::__1::__wrap_iter<std::__1::__wrap_iter<char *> *>, long>' to 'const std::__1::vector<char,
      std::__1::allocator<char> >' for 1st argument
    vector(const vector& __x, const allocator_type& __a);
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:574:5: note: candidate constructor not viable:
      no known conversion from 'iter::IteratorIterator<std::__1::__wrap_iter<std::__1::__wrap_iter<char *> *>, long>' to
      'std::__1::vector<char, std::__1::allocator<char> >' for 1st argument
    vector(vector&& __x, const allocator_type& __a);
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:525:35: note: candidate template ignored:
      disabled by 'enable_if' [with _InputIterator = iter::IteratorIterator<std::__1::__wrap_iter<std::__1::__wrap_iter<char *> *>, long>]
               typename enable_if<__is_input_iterator  <_InputIterator>::value &&
                                  ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:540:35: note: candidate template ignored:
      disabled by 'enable_if' [with _ForwardIterator = iter::IteratorIterator<std::__1::__wrap_iter<std::__1::__wrap_iter<char *> *>, long>]
               typename enable_if<__is_forward_iterator<_ForwardIterator>::value &&
                                  ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:532:9: note: candidate constructor template not
      viable: requires at least 3 arguments, but 2 were provided
        vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a,
        ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:546:9: note: candidate constructor template not
      viable: requires at least 3 arguments, but 2 were provided
        vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a,
        ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:510:40: note: candidate constructor not viable:
      requires single argument '__a', but 2 arguments were provided
    _LIBCPP_INLINE_VISIBILITY explicit vector(const allocator_type& __a)
                                       ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:517:14: note: candidate constructor not viable:
      requires single argument '__n', but 2 arguments were provided
    explicit vector(size_type __n);
             ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:553:5: note: candidate constructor not viable:
      requires single argument '__il', but 2 arguments were provided
    vector(initializer_list<value_type> __il);
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:565:5: note: candidate constructor not viable:
      requires single argument '__x', but 2 arguments were provided
    vector(const vector& __x);
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:571:5: note: candidate constructor not viable:
      requires single argument '__x', but 2 arguments were provided
    vector(vector&& __x)
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:522:5: note: candidate constructor not viable:
      requires 3 arguments, but 2 were provided
    vector(size_type __n, const_reference __x, const allocator_type& __a);
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:503:5: note: candidate constructor not viable:
      requires 0 arguments, but 2 were provided
    vector()
    ^
1 error generated.
scons: *** [test_combinations.o] Error 1
scons: building terminated because of errors.

VS2019 compilation errors iter::chain (fix planned for 16.4)

Hello,
few time ago I was trying to compile CppIterTools with VS2019 and I get errors with iter::chain with this kind of errors:

iterbase.hpp(94,36): error C2672:  'iter::impl::get_iters::get_begin': no matching overloaded function found
iterbase.hpp(94,1): error C2893:  Failed to specialize function template 'unknown-type iter::impl::get_iters::get_begin(T &)'
iterbase.hpp(104,43): error C2672:  'std::declval': no matching overloaded function found
iterbase.hpp(104,1): error C2893:  Failed to specialize function template '_Add_reference<_Ty,void>::_Rvalue std::declval(void) noexcept'

I have filled a bug to Microsoft and they seem to have fix the bug in their compiler on 16.4 version which isn't yet release (maybe a month or 2).
Here is the link:
https://developercommunity.visualstudio.com/content/problem/638663/vs2019-c-failed-to-specialize-sfinae-regression.html

group_by a tuple key

Hi, I am trying to group_by a tuple key:

struct A {
    int key1;
    int key2;
    int x;
    int y;
    int value;
};

void func() {
    using namespace std;

    // inputs
    std::vector<int> uniquex{ 1, 2 };
    std::vector<int> uniquey{ 1, 2 };
    vector<A> vec{
        { 10, 9, 1, 1, 5 },     { 10, 9, 1, 2, 6 },     
        { 10, 10, 1, 1, 1 },    { 10, 10, 1, 2, 2 },
        { 10, 9, 2, 1, 7 },     { 10, 9, 2, 2, 8 },
        { 10, 10, 2, 1, 3 },    { 10, 10, 2, 2, 4 },
    };
    auto keyFunc = [](const A& a) { return make_tuple(a.key1, a.key2); };

    for (auto&& gb : iter::groupby(vec, keyFunc)) {
        std::cout << "key(" << std::get<0>(gb.first) << "," << std::get<1>(gb.first) << "): ";
                for (auto&& s : gb.second) {
                        std::cout << s.value << "  ";
                }
                std::cout << '\n';
        }

Instead of printing 2 lines, this example prints four lines. Does the groupby intent to work with group data not next to each other?

Feature request: Something like list comprehension

First, I love this library. As soon as I first read of range-based for loops, I wanted this. Now, the feature request...

It would be great to have a way to transform all of the elements in an iterator, as is often done with list comprehensions in python.

for (auto&& p : transform([](int x) { return x*x; }, range(10))) { /* ... */ }

or

for (auto&& p : range(10) | transform([](int x) { return x*x; })) { /* ... */ }

If there is some magic in C++ to do this already, perhaps that can go as an example in the readme.

`iter::reversed` vs. `std::rbegin`/`std::rend`

Hi,

I don't know if this counts as a bug. However, here's the issue.
I was trying to use iter::reversed together with boost::irange. The following toy example does not compile:

#include <boost/range/irange.hpp>
#include <itertools/reversed.hpp>

int main() {

    auto r = boost::irange(0, 10);
    for (auto&& i: iter::reversed(r)) 
        std::cout << i << std::endl;

} 

the output reads:

error: no member named 'rbegin' in 'boost::integer_range<int>'
        decltype(std::declval<Container&>().rbegin());

A workaround could be to use the free functions std::rbegin and std::rend, although this would break C++11 compatibility.

Thanks.

Combining reversed with zip (and possibly others)

I tried to use reversed in conjunction with zip in a ranged-based for loop, i.e.

for (auto&& tup : reversed(zip(container1, container2))) { ... }

Unfortunately, this results in error messages stating that there is no rbegin() function. Indeed, I didn't find that function in zip.hpp. Are there any plans to add this functionality, possibly also to the other range expressions?

cannot iterate over const chain object.

The following fails, can't construct the iterator

#include <vector>

#include "cppitertools/chain.hpp"

int main() {
  std::vector<char> v1 = {'a'};
  std::vector<char> v2 = {'b'};
  const auto ch = iter::chain(v1, v2);
  std::begin(ch);
}

Because the chain begin() const is saying that the iterator needs a const tuple<Ts...> while what it actually gets is tuple<const Ts...>

`error: 'rbegin' is not a member of 'std'` - C++11 compliancy

I am experiencing problems compiling with gcc-4.9.3. On trying to compile a simple zip, I get the following error message:

cppitertools/reversed.hpp:29:16: error: 'rbegin' is not a member of 'std'

It seems to me that this issue is due to cppitertools using C++14 features and my standard library not being C++14 compliant, as is explained here.
Should the library still work in a C++11 environment or is there some other problem on my behalf?

Edit:
I now tested with gcc-5.3 and -std=c++11, which gives similar errors. Activating -std=c++14 fixes the problem.
The issue boils down to:

Implementation of python itertools and builtin iteration functions for C++14

[c++17] enumerate should work with structured bindings

Currently this is invalid with c++17

for (auto&& [i, e] : iter::enumerate(seq)) {
    // ...
}

because the object returned by enumerate's iterator's operator* is a subclass of pair with more data members. In some way, the above should work.

Default include

Hi.

Gr8 library.

It would be very helpful if all includes used "" instead of <>. That way, there is no need to add the entire cppitertools directory to the include path, e.g. It would be better to just drop the entire library in the regular include path and just do

include <cppitertools/itertools.hpp>

and everything will work.

Building and Running tests

I'm not sure how to build and test the project. I've managed to build the tests by running ./download_catch.sh and running scons in the test folder. I can run these tests manually, but I'm sure thats not the proper way.

How should the project be built and tested with Bazel and scons?

groupby support for automatic exhaustion of skipped groups

The current implementation of groupby relies on exhausting the elements of each group in order. With Python's groupby, once one tries to access the n+1th group, the nth grouping becomes invalid, so it is not necessary that random accessing of groups be supported.

The C++ implementation does not support short-circuting the evaluation of a group or skipping of a group entirely, a continue in the outer loop results in unexpected behavior. It must support the C++ equivalent of

for length, group in groupby(words, len):
    if length == 4: 
        continue
    for e in group: 
        print(e)

I'm not sure how to best handle this yet. It seems the logic will have to go either in the Group class's destructor, or in GroupBy::Iterator::operator++()

count is not actually infinite

This is just a little nitpick, but I was reading you code base and realized that iter::count is doing limit checking and the explanation is a bit off

Effectively a range without a stopping point.

Although in signed integers overflow is undefined, it is defined in unsigned integers as wraparound but the below loop ends at 65534. (One before the limit)

using T = unsigned short;
    for(auto i : iter::count(T{})) {
        if(cond)
            break;
    }

I think more reasonable behaviour is just incrementing the counter by step at each iteration without doing a boundary check and let it fail if it ever hits an undefined behaviour. In here you are basically defining the behaviour.

However as I said at the beginning, this is just a little nitpick regarding the documentation and it would be still fine to keep the behaviour as it is but with proper explanation in the documentation.

Drop support for deduced std::initializer_list

Maintaining everything with duplicate functions that can deduce std::initializer_list feels like more trouble than it's worth. I doubt anyone makes use of it (I don't), especially because none of the variadic functions can support it and I haven't heard any complaints.

Will be likely be removed alongside the | operator updates (unless anyone out there says they've used these functions for real).

zip.hpp doesn't compile with gcc 8.2.1

$ g++ examples/zip_examples.cpp -I ./ -std=c++17
In file included from examples/zip_examples.cpp:1:
./zip.hpp: In instantiation of ‘class iter::impl::Zipped<std::tuple<std::vector<int, std::allocator >&, std::vector<std::__cxx11::basic_string<char, std::char_traits, std::allocator >, std::allocator<std::__cxx11::basic_string<char, std::char_traits, std::allocator > > >&>, 0, 1>::Iterator<std::tuple<std::vector<int, std::allocator >&, std::vector<std::__cxx11::basic_string<char, std::char_traits, std::allocator >, std::allocator<std::__cxx11::basic_string<char, std::char_traits, std::allocator > > >&>, iter::impl::iterator_tuple_type, iter::impl::iterator_deref_tuple>’:
examples/zip_examples.cpp:13:46: required from here
./zip.hpp:41:60: error: template parameter ‘template<class TupleType, long unsigned int ...Is> template class IteratorTuple’
template <typename TupleTypeT, template class IteratorTuple,
^~~~~~~~~~~~~
./zip.hpp:46:18: error: redeclared here as ‘template class’
friend class Iterator;
^~~~~~~~

$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /build/gcc/src/gcc/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/ --enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++ --enable-shared --enable-threads=posix --enable-libmpx --with-system-zlib --with-isl --enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --disable-libssp --enable-gnu-unique-object --enable-linker-build-id --enable-lto --enable-plugin --enable-install-libiberty --with-linker-hash-style=gnu --enable-gnu-indirect-function --enable-multilib --disable-werror --enable-checking=release --enable-default-pie --enable-default-ssp --enable-cet=auto
Thread model: posix
gcc version 8.2.1 20180831 (GCC)

vector<bool> and groupby

Hi

I'm getting another strange behaviour:

  vector<bool> v{true, true, false, false,false, true, true};
  for (auto &&x: iter::groupby(v,[](auto b){return b;})) {
    cout << "group: ";
    for (auto &&g: x.second)
      cout << g << " ";
    cout << endl;
  }

prints

group: 1 1 0 0 0 1 1 

yet

  vector<int> v{5,5,5,3,3};
  for (auto &&x: iter::groupby(v,[](auto b){return b;})) {
    cout << "group: ";
    for (auto &&g: x.second)
      cout << g << " ";
    cout << endl;
  }

prints

group: 5 5 5 
group: 3 3

Is there a reason why it shouldn't work with bool ?

count not working for negative non-integer step

The following statements do not work:

const std::vector<double> expected{1.0, 0.5, 0.0, -0.5, -1.0};
  std::vector<double> counted;
  for (auto c : count(1.0, -0.5)) {
    counted.push_back(c);
    if (c <= -1.0) break;
  }
  for (int i : range(expected.size()))
    EXPECT_DOUBLE_EQ(expected[i], counted[i]);

Output errors:

Expected equality of these values: expected[i] Which is: 0 counted[i] Which is: 2.1219957913605248e-313 /home/pedrogf/Projects/LightFields/ReferenceSoftware/REPO/jplm/source/Tests/ThirdParty/CppIterToolsTests.cpp:471: Failure Expected equality of these values: expected[i] Which is: -0.5 counted[i] Which is: 1.0325971998082053e-321 /home/pedrogf/Projects/LightFields/ReferenceSoftware/REPO/jplm/source/Tests/ThirdParty/CppIterToolsTests.cpp:471: Failure Expected equality of these values: expected[i] Which is: -1 counted[i] Which is: 0

However, the equivalent Python code works fine:

import itertools
for i in itertools.count(1.0, -0.5):
     print(i)
     if i <= -1:
         break

1.0 0.5 0.0 -0.5 -1.0

Support for move only types

Hi,

I would like to use the library with move only types. Here's a toy example:

#include <iostream>
#include <vector>
#include <itertools/product.hpp>

struct MoveOnlyType {
    MoveOnlyType() = default;
    MoveOnlyType(MoveOnlyType const& other) = delete;
    MoveOnlyType(MoveOnlyType&& other) = default;
    MoveOnlyType& operator=(MoveOnlyType const& other) = delete;
    MoveOnlyType& operator=(MoveOnlyType&& other) = default;
};

int main() {

    std::vector<MoveOnlyType> v1, v2;
    v1.push_back(MoveOnlyType());
    v1.push_back(MoveOnlyType());

    v2.push_back(MoveOnlyType());
    v2.push_back(MoveOnlyType());
    v2.push_back(MoveOnlyType());


    for (auto&& pair_of_moveonly: iter::product(v1, v2)) 
        std::cout << "it does not work" << std::endl;
}

Thanks.

`iter::product` of `iter::range`'s

Hi,

I was trying to compose iter::product with iter::range so as to iterate over all the coordinate pairs of a matrix. Unfortunately, I can't manage to get it work with iter::range, wheres there's no problem with ranges generated with boost::irange. Here's a showcase example:

int main() {

    // this work
    for (auto&& ij: iter::product(boost::irange(0, 10), boost::irange(0, 5))) {
        std::cout << std::get<0>(ij) << "," << std::get<1>(ij) << std::endl;
    }

    // this does not work
    for (auto&& ij: iter::product(iter::range(10), iter::range(5))) {
        std::cout << std::get<0>(ij) << "," << std::get<1>(ij) << std::endl;
    }   
}

clang reports:

note: copy assignment operator of 'Iterator' is implicitly deleted because field 'step' is of const-qualified type 'const int'
                    const T step;

Thanks and sorry for submitting two reports in a row!

Boost unit tests

We have a whole testing directory right now and the tests are fine. But I want to adapt them to use the boost unit test framework, this will make the tests more useful by actually checking something instead of just running and exiting

Add compiler compatibility list

Can you please add the list of compatible compilers?
VS 2013 does not support noexcept while VS 2015 finds "unknown size" errors everywhere.

Severity  Code  Description  Project  File  Line  Suppression State
Error  C2133  ' ?? ?? :: ?? ::derefers': unknown size  ...\include\cppitertools\chain.hpp  72

Consider overloading the "pipe" operator

Hi,

Often, I find myself mixing together cppitertools and boost.range (and – more recently – range-v3). I believe that supporting the (de-facto standard) pipe operator | would greatly improve the interoperability between the different range libraries.

Thanks.

imap function applied multiple times

I am trying to translate this (simplified) example from python (2.7) to C++ (tried both clang 3.4 and gcc 4.7) using move-only objects.

Python snippet, prints 41 43:

import itertools as it

class MyItem:
    def __init__(self, val):
        self.val = val
    def with_val(self, val):
        self.val = val
        return self

if "__main__" == __name__:
    vec = [MyItem(41), MyItem(42), MyItem(43)]
    transformed1 = it.imap(lambda el: el.with_val(el.val + 10), vec)
    filtered = it.ifilter(lambda el: 52 != el.val, transformed1)
    transformed2 = it.imap(lambda el: el.with_val(el.val - 10), filtered)

    for el in transformed2:
        print(el.val)

C++ snippet, prints 51 53:

#include <iostream>
#include <vector>

#include "imap.hpp"
#include "filter.hpp"

class MyMoveOnly {
    int val;
public:
    MyMoveOnly() { };
    MyMoveOnly(int val) : val(val) { }
    MyMoveOnly(const MyMoveOnly&) = delete;
    MyMoveOnly& operator=(const MyMoveOnly&) = delete;
    MyMoveOnly(MyMoveOnly&& other) : val(other.val) { }
    MyMoveOnly& operator=(MyMoveOnly&& other) {
        this->val = other.val;
        return *this;
    }
    int get_val() {
        return val;
    }
    void set_val(int val) {
        this->val = val;        
    }
};

namespace it = iter;

int main() {
    // source data
    std::vector<MyMoveOnly> vec{};
    vec.emplace_back(MyMoveOnly(41));
    vec.emplace_back(MyMoveOnly(42));
    vec.emplace_back(MyMoveOnly(43));
    // some transformations
    auto transformed1 = it::imap([](MyMoveOnly& el) {
        int va = el.get_val();
        el.set_val(va + 10);
        return std::move(el);
    }, vec);
    // r-value ref is used here because l-value ref won't compile
    auto filtered = it::filter([](MyMoveOnly&& el) {
        return 52 != el.get_val();
    }, transformed1);
    auto transformed2 = it::imap([](MyMoveOnly& el) {
        int va = el.get_val();
        el.set_val(va - 10);
        return std::move(el);
    }, filtered);
    // print data
    for (auto&& el : transformed2) {
        std::cout << el.get_val() << std::endl;
    }

    return 0;
}

I wasn't sure that this example will compile (because of non-copyable objects), it actually compiles and runs, but the first transformation is applied twice for each element. I am not sure whether this is intended behaviour, but it is definitely contr-intuitive because single foreach over the transformed sequence caused multiple applyings of imap function.

arguments for product

  • in many use cases, the number of arguments for a function like this is known only at run time. is it possible for product to accept a vector object?
  • or add something equivalent to Python's unpacking operator (*) to cppitertools?

Filtering `iter::product`

Hi,

with respect to #16, I was trying to filter out the upper right corner of the matrix using iter::filter. Here's the showcase code:

int main() {

    auto range = iter::product(iter::range(10), iter::range(5));

    for (auto&& ij: iter::filter([](std::tuple<unsigned, unsigned> const& c) {return std::get<0>(c) >= std::get<1>(c);}, range))
        std::cout << std::get<0>(ij) << "," << std::get<1>(ij) << std::endl;
}

Unfortunately, this does not compile. Clang reads:

error: indirection requires pointer operand ('const iterator_type<iter::Productor<iter::Range<int>, iter::Range<int> > &>' (aka 'const iter::Productor<iter::Range<int>, iter::Range<int> >::Iterator') invalid)
                        return *this->sub_iter;

Same error if I replace iter::filter with boost::adaptors::filtered, so I presume the error should be in iter::Producter.

Thanks.

combination of chunked -> filter -> imap = bogus results

Hi

The following code is a minimal reproducer of an issue I'm getting.

vector<int16_t> v(10000, 0);
  auto a = iter::chunked(v,480);
  auto b = iter::filter([](auto & chunk){ return true;}, a);
  auto c = iter::imap([](auto & chunk){ cout << chunk.size() << " "; return 1;}, b);
  for(auto &&x: c);

prints

18446738293966284791 480 480 480 480 480 480 480 480 480 480 480 480 480 480 480 480 480 480 480 400

The first chunk size is always bogus. Inside the first chunk there are also bogus values.

Is this a bug, or I'm I doing something wrong ?

Using SFINAE to detect for certain methods

For example slice currently needs a random access iterator. We should detect if one exists for the iterable if it doesn't a different method of using slice should be used

Can't dereference const zip iterator

#include <vector>

#include "zip.hpp"

int main()
{
    std::vector<int> a(1);

    const auto it = iter::zip(a).begin();
    const auto [v] = *it;

    return v;
}

[ilya@ilya-pc cppitertools]$ clang++ const_iter.cpp -I ./ -std=c++17 -fno-permissive
const_iter.cpp:11:22: error: indirection requires pointer operand ('const iter::impl::Zipped<std::tuple<std::vector<int, std::allocator > &>, 0>::Iterator<std::tuple<std::vector<int, std::allocator > &>, iterator_tuple_type, iterator_deref_tuple>' invalid)
const auto [v] = *it;

Is there a reason for Zipped::Iterator::operator*() not to be const?
https://github.com/ryanhaining/cppitertools/blob/master/zip.hpp#L90

The cmake version config file is not installed alongside the config file

According to https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html, the cmake version config file should be installed alongside the cmake config file; however:

install(EXPORT cppitertools-targets
        FILE cppitertools-config.cmake
        NAMESPACE cppitertools::
        DESTINATION ${cppitertools_INSTALL_CMAKE_DIR}/cppitertools
        )

install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cppitertools-config-version.cmake DESTINATION ${cppitertools_INSTALL_CMAKE_DIR})

is how the version file is installed -- afaict, this is a silent failure to use the version file. It seems that the DESTINATION should probably be ${cppitertools_INSTALL_CMAKE_DIR}/cppitertools, like the cppitertools-config.cmake file.

Combining enumerate with filter

Hello,
as fist step, thanks for this great library!

Now with the issue:

std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8};

auto f = iter::enumerate(v) | iter::filter([](auto& i) { return std::get<1>(i) > 4; });

for (auto&& [i, e]: f) {
    std::cout << i << ", " << e << '\n';
}

This snippet doesn't compile (g++ 7.4), with error:

error: use of deleted function ‘std::optional<iter::impl::EnumIterYield<long unsigned int, int&> >& std::optional<iter::impl::EnumIterYield<long unsigned int, int&> >::operator=(std::optional<iter::impl::EnumIterYield<long unsigned int, int&> >&&)’

I opened StackOverflow question, since I'm not sure if I didn't do something wrong - https://stackoverflow.com/questions/57648457/cppitertools-how-to-combine-iterenumerate-and-iterfilter

Is it possible to combine filter with enumerate this way? The solutions appears is to change iterbase.hpp:301 from item_p_ = std::move(item); to item_p_.emplace(std::move(item));

Can't chain a `std::set` with an `std::vector`

This simple example fails to compile:

#include <stdlib.h>
#include "cppitertools/chain.hpp"

std::vector<const char *> c1 = {"a", "b", "c"};
std::set<const char *> c2 = {"d", "d", "e"};
for (auto n : iter::chain(c1, c2))
{
    std::cout << n << std::endl;
}

The following errors are raised:

in instantiation of function template specialization 'iter::impl::ChainMaker::operator()<std::vector<const char *,
      std::allocator<const char *> > &, std::set<const char *, std::less<const char *>, std::allocator<const char *> >
      &>' requested here
for (auto n : iter::chain(c1, c2)) {std::cout << n << std::endl;}
                         ^

inconsistent type deduction behavior with old imap and new(starmap) imap implementation

In the older version of imap, which was not implemented on top of starmap, you could say something like

auto fn = []{};
using MapType = decltype(iter::imap(fn, 1));

MapType isn't terribly useful here, you couldn't actually iterate through it, but the behavior is consistent with most other itertools. In the new version, the above code fails to compile.

groupby segmentation fault

Hi

I'm getting a segmentation fault with the following code:

  std::vector<int> v{true,true,true,false,false,true,true};
  auto a = iter::groupby(v,[](bool b){return b;});
  auto b = iter::filter([](auto &g){ return g.first;},a);
  auto c = iter::imap([](auto &g){ return std::distance(g.second.begin(), g.second.end()); }, b);
  for (size_t x: c)
    std::cout << x;

I'm trying to get the size of the longest sequence of trues.

Program received signal SIGSEGV, Segmentation fault.
0x00005555556117b1 in __gnu_cxx::operator!=<int*, std::vector<int, std::allocator<int> > > (__lhs=<error reading variable: Cannot access memory at address 0x0>, __rhs=<error reading variable: Cannot access memory at address 0x8>) at /usr/include/c++/8/bits/stl_iterator.h:887
887	    { return __lhs.base() != __rhs.base(); }

#0  0x00005555556117b1 in __gnu_cxx::operator!=<int*, std::vector<int, std::allocator<int> > > (__lhs=<error reading variable: Cannot access memory at address 0x0>, __rhs=<error reading variable: Cannot access memory at address 0x8>) at /usr/include/c++/8/bits/stl_iterator.h:887
#1  0x00005555555e99e2 in iter::impl::GroupProducer<std::vector<int, std::allocator<int> >&, main(int, char**)::<lambda(bool)> >::Iterator<std::vector<int, std::allocator<int> >&>::increment_iterator(void) (this=0x0) at /home/miguel/Development/IPL/investigacao/vad_check/cppitertools/groupby.hpp:148
#2  0x00005555555e951b in iter::impl::GroupProducer<std::vector<int, std::allocator<int> >&, main(int, char**)::<lambda(bool)> >::Group<std::vector<int, std::allocator<int> >&>::GroupIterator::operator++(void) (this=0x7fffffffc520) at /home/miguel/Development/IPL/investigacao/vad_check/cppitertools/groupby.hpp:247
#3  0x00005555555e9088 in std::__distance<iter::impl::GroupProducer<std::vector<int>&, main(int, char**)::<lambda(bool)> >::Group<std::vector<int>&>::GroupIterator>(iter::impl::GroupProducer<std::vector<int, std::allocator<int> >&, main(int, char**)::<lambda(bool)> >::Group<std::vector<int, std::allocator<int> >&>::GroupIterator, iter::impl::GroupProducer<std::vector<int, std::allocator<int> >&, main(int, char**)::<lambda(bool)> >::Group<std::vector<int, std::allocator<int> >&>::GroupIterator, std::input_iterator_tag) (__first=..., __last=...) at /usr/include/c++/8/bits/stl_iterator_base_funcs.h:89
#4  0x00005555555e8843 in std::distance<iter::impl::GroupProducer<std::vector<int>&, main(int, char**)::<lambda(bool)> >::Group<std::vector<int>&>::GroupIterator>(iter::impl::GroupProducer<std::vector<int, std::allocator<int> >&, main(int, char**)::<lambda(bool)> >::Group<std::vector<int, std::allocator<int> >&>::GroupIterator, iter::impl::GroupProducer<std::vector<int, std::allocator<int> >&, main(int, char**)::<lambda(bool)> >::Group<std::vector<int, std::allocator<int> >&>::GroupIterator) (__first=..., __last=...) at /usr/include/c++/8/bits/stl_iterator_base_funcs.h:141
#5  0x00005555555e6d10 in <lambda(auto:5&)>::operator()<std::pair<bool, iter::impl::GroupProducer<std::vector<int>&, main(int, char**)::<lambda(bool)> >::Group<std::vector<int>&> > >(std::pair<bool, iter::impl::GroupProducer<std::vector<int>&, main(int, char**)::<lambda(bool)> >::Group<std::vector<int, std::allocator<int> >&> > &) const (__closure=0x7fffffffc870, g={...}) at /home/miguel/Development/IPL/investigacao/vad_check/src/main.cc:456
#6  0x00005555555e90cc in std::__invoke_impl<long int, main(int, char**)::<lambda(auto:5&)>&, std::pair<bool, iter::impl::GroupProducer<std::vector<int>&, main(int, char**)::<lambda(bool)> >::Group<std::vector<int, std::allocator<int> >&> >&>(std::__invoke_other, <lambda(auto:5&)> &, std::pair<bool, iter::impl::GroupProducer<std::vector<int>&, main(int, char**)::<lambda(bool)> >::Group<std::vector<int, std::allocator<int> >&> > &) (__f=..., __args#0={...}) at /usr/include/c++/8/bits/invoke.h:60
#7  0x00005555555e887c in std::__invoke<main(int, char**)::<lambda(auto:5&)>&, std::pair<bool, iter::impl::GroupProducer<std::vector<int>&, main(int, char**)::<lambda(bool)> >::Group<std::vector<int, std::allocator<int> >&> >&>(<lambda(auto:5&)> &, std::pair<bool, iter::impl::GroupProducer<std::vector<int>&, main(int, char**)::<lambda(bool)> >::Group<std::vector<int, std::allocator<int> >&> > &) (__fn=..., __args#0={...}) at /usr/include/c++/8/bits/invoke.h:95
#8  0x00005555555e6d5a in std::__apply_impl<main(int, char**)::<lambda(auto:5&)>&, std::tuple<std::pair<bool, iter::impl::GroupProducer<std::vector<int>&, main(int, char**)::<lambda(bool)> >::Group<std::vector<int, std::allocator<int> >&> >&>, 0>(<lambda(auto:5&)> &, std::tuple<std::pair<bool, iter::impl::GroupProducer<std::vector<int>&, main(int, char**)::<lambda(bool)> >::Group<std::vector<int, std::allocator<int> >&> >&> &&, std::index_sequence) (__f=..., __t=...) at /usr/include/c++/8/tuple:1678
#9  0x00005555555e6d98 in std::apply<main(int, char**)::<lambda(auto:5&)>&, std::tuple<std::pair<bool, iter::impl::GroupProducer<std::vector<int>&, main(int, char**)::<lambda(bool)> >::Group<std::vector<int, std::allocator<int> >&> >&> >(<lambda(auto:5&)> &, std::tuple<std::pair<bool, iter::impl::GroupProducer<std::vector<int>&, main(int, char**)::<lambda(bool)> >::Group<std::vector<int, std::allocator<int> >&> >&> &&) (__f=..., __t=...) at /usr/include/c++/8/tuple:1687
#10 0x00005555555e6e6b in iter::impl::StarMapper<main(int, char**)::<lambda(auto:5&)>, iter::impl::Zipped<std::tuple<iter::impl::Filtered<main(int, char**)::<lambda(auto:4&)>, iter::impl::GroupProducer<std::vector<int, std::allocator<int> >&, main(int, char**)::<lambda(bool)> >&>&>, 0> >::Iterator<iter::impl::Zipped<std::tuple<iter::impl::Filtered<main(int, char**)::<lambda(auto:4&)>, iter::impl::GroupProducer<std::vector<int, std::allocator<int> >&, main(int, char**)::<lambda(bool)> >&>&>, 0> >::operator*(void) (this=0x7fffffffc6f0) at /home/miguel/Development/IPL/investigacao/vad_check/cppitertools/starmap.hpp:86
#11 0x00005555555e7998 in main (argc=3, argv=0x7fffffffd948) at /home/miguel/Development/IPL/investigacao/vad_check/src/main.cc:458

Also, wouldn't it be useful to have a function which calculates the number of elements of an iterator like std::distance(iterator.begin(), iterator.end()); ?

For comparison, the same thing in Haskell:

Prelude Data.List> x = [True,True,True,False,False,True]
Prelude Data.List> group x
[[True,True,True],[False,False],[True]]
Prelude Data.List> fmap length $ filter (!!0) $ group x
[3,1]
Prelude Data.List> sortDesc = sortBy (flip compare)
Prelude Data.List> head $ sortDesc $ fmap length $ filter (!!0) $ group x
3

Appveyor MSVC 2019 build failing

the build log includes a CMake error:

CMake Error at C:/Program Files (x86)/CMake/share/cmake-3.15/Modules/FindPackageHandleStandardArgs.cmake:137 (message):
  Could NOT find Boost (missing: Boost_INCLUDE_DIR) (Required is at least
  version "1.60.0")
Call Stack (most recent call first):
  C:/Program Files (x86)/CMake/share/cmake-3.15/Modules/FindPackageHandleStandardArgs.cmake:378 (_FPHSA_FAILURE_MESSAGE)
  C:/Program Files (x86)/CMake/share/cmake-3.15/Modules/FindBoost.cmake:2161 (find_package_handle_standard_args)
  CMakeLists.txt:12 (find_package)

Appveyor only has Boost 1.71.0 for MSVC 2019, but the highest it has for MSVC 2017 is Boost 1.69.0.

The BOOST_ROOT environment variable in the appveyor setting is set to C:\Libraries\boost_1_64_0, but of course this only works for MSVC 2017

Both MSVC 2017 and 2019 work when they have their respective correct BOOST_ROOT

request zip/zip_longest functionality

Hi, good to see more Python like functions in c++.

Is it possible to have zip and zip_longest use a single iterator over an arbitrary number of containers that are only known at runtime? Just like in Python when unpacking a list of lists? It would really be helpful for me.

sorted: can modify elements - why normal?

Hi. I don't understand the code in the test/test_sorted.cpp:

  std::vector<int> ns(3, 9);
  for (auto&& n : sorted(ns)) {
    n = -1;
  }
  Vec vc(3, -1);
  REQUIRE(ns == vc);

Why so? Doesn't vc must be (-1, -1)? Can you explain?

Make available via conan

Conan is besides Microsoft's vcpkg the most popular package manager for C++ out there. But with good support for cmake and linux in contrast to vcpkg.
We use them it in our C++ projects to pull in dependencies without including them into our source code or installing them on the building system. See for example https://bintray.com/stiffstream/public/restinio%3Astiffstream for how libraries are published on conan.

Would you consider to publish cppitertools on conan? We could help with conanizing cppitertools.

FYI @Shaheen47

Support for std::begin & std::end

I have noted that your the container class must have a .begin() method otherwise you cannot declare the iterators. However, if you use declvar any iterable that support std::begin() (like static arrays) will also work in your framework. For instance, here's how I would declare a typedef for iterator_type:

typedef decltype(std::begin(std::declval<Iterable&>())) iterator_type;

Now the iterable can be:

  • vector
  • static array
  • map
    ..

Uses features from C++14

iterbase.hpp uses std::enable_if_t, which was not added until C++14. The repository description indicates that this is a C++11 library, and nowhere in the readme does it mention that C++14 support is required.

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.