Coder Social home page Coder Social logo

cpp11's People

Contributors

alyst avatar batpigandme avatar bkietz avatar davisvaughan avatar emilhvitfeldt avatar eutwt avatar hadley avatar indrajeetpatil avatar jennybc avatar jeroen avatar jimhester avatar jonthegeek avatar kevinushey avatar klmr avatar michaelchirico avatar mpadge avatar nealrichardson avatar pachadotdev avatar patrickvossler18 avatar renkun-ken avatar richfitz avatar romainfrancois avatar sbearrows avatar tcpan avatar thisisnic avatar thomasp85 avatar tmastny avatar vspinu avatar xhochy avatar yutannihilation 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

cpp11's Issues

initializer_list constructors for cpp11:: types

Would it be useful to have the initializer lists constructors also for the non writable classes, or should they really only be constructed from SEXP, e.g. I enjoy:

cpp11::cpp_function('cpp11::writable::strings words() {
  return {"person", "man", "woman", "camera", "tv"};
}')
words()
#> [1] "person" "man"    "woman"  "camera" "tv"

but this would be useful too:

cpp11::cpp_function('cpp11::strings words() {
  return {"person", "man", "woman", "camera", "tv"};
}', quiet = FALSE)
#> clang++ -mmacosx-version-min=10.13 -std=gnu++11 -I"/Library/Frameworks/R.framework/Resources/include" -DNDEBUG -I/Users/romainfrancois/.R/library/4.0/cpp11/include  -I/usr/local/include   -fPIC  -Wall -O3 -Wall -Wimplicit-int-float-conversion -c /private/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T/RtmphIuzJv/filebd3a13b05d00/src/code_1.cpp -o /private/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T/RtmphIuzJv/filebd3a13b05d00/src/code_1.o
#> /private/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T/RtmphIuzJv/filebd3a13b05d00/src/code_1.cpp:6:10: error: no matching constructor for initialization of 'cpp11::strings' (aka 'r_vector<cpp11::r_string>')
#>   return {"person", "man", "woman", "camera", "tv"};
#>          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#> /Users/romainfrancois/.R/library/4.0/cpp11/include/cpp11/r_vector.hpp:61:3: note: candidate constructor not viable: requires 2 arguments, but 5 were provided
#>   r_vector(SEXP data, bool is_altrep);
#>   ^
#> /Users/romainfrancois/.R/library/4.0/cpp11/include/cpp11/r_vector.hpp:59:3: note: candidate constructor not viable: requires single argument 'data', but 5 arguments were provided
#>   r_vector(SEXP data);
#>   ^
#> /Users/romainfrancois/.R/library/4.0/cpp11/include/cpp11/r_vector.hpp:91:3: note: candidate constructor not viable: requires single argument 'rhs', but 5 arguments were provided
#>   r_vector(const r_vector& rhs) {
#>   ^
#> /Users/romainfrancois/.R/library/4.0/cpp11/include/cpp11/r_vector.hpp:57:3: note: candidate constructor not viable: requires 0 arguments, but 5 were provided
#>   r_vector() = default;
#>   ^
#> 1 error generated.
#> make: *** [/private/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T/RtmphIuzJv/filebd3a13b05d00/src/code_1.o] Error 1
#> Error in dyn.load(shared_lib, local = TRUE, now = TRUE): unable to load shared object '/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T//RtmphIuzJv/filebd3a13b05d00/src/code_1.so':
#>   dlopen(/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T//RtmphIuzJv/filebd3a13b05d00/src/code_1.so, 6): image not found
words()
#> Error in .Call("_code_1_words", PACKAGE = "code_1"): "_code_1_words" not available for .Call() for package "code_1"

Created on 2020-07-24 by the reprex package (v0.3.0.9001)

as_cpp<Enum>

It would be nice to have some mechanism to move enums back and forth between R and C++. I'm not sure what as_sexp() would do but as_cpp<Enum> could be:

namespace cpp11 {

template <typename E>
typename std::enable_if<std::is_enum<E>::value, E>::type as_cpp(SEXP from) {
  return E(cpp11::as_cpp<typename std::underlying_type<E>::type>(from));
}

}

If this is of interest, I'll polish and make it a proper pull request.

In Rcpp we had to use the RCPP_EXPOSED_ENUM_NODECL macro to declare each enum we wished to expose, manually, which sets some templates for Rcpp::as<> and Rcpp::wrap<>. IIRC, Rcpp cannot use the is_enum trait because it's a C++11 thing. https://github.com/RcppCore/Rcpp/blob/f3c5a34e06e774532227470b01c63a8f08ce4313/inst/include/Rcpp/macros/module.h#L76

rename `[[cpp11::export]]`

export is a nice term, but is unfortunately somewhat confusing due to roxygen2 and NAMESPACE using export for exported functions.

[[cpp11::use_from_r]] seems to match the intent of the attribute best and is nicely self documenting.

Release cpp11 0.1.0

Prepare for release:

  • Check that description is informative
  • Check licensing of included files
  • usethis::use_cran_comments()
  • devtools::check(remote = TRUE, manual = TRUE)
  • devtools::check_win_devel()
  • rhub::check_for_cran()
  • Update cran-comments.md
  • Review pkgdown reference index for, e.g., missing topics
  • Draft blog post

Submit to CRAN:

  • usethis::use_version('minor')
  • devtools::submit_cran()
  • Approve email

Wait for CRAN...

  • Accepted 🎉
  • usethis::use_news_md()
  • usethis::use_github_release()
  • usethis::use_dev_version()
  • Update install instructions in README
  • Finish blog post
  • Tweet
  • Add link to blog post in pkgdown news menu

Default arguments?

Should the code generator support having default arguments? I am not sure, it would only work for numeric (and boolean) values and would add complexity to the generation code.

But maybe it is worth it.

enable_if typedefs are not idiomatically named

Names matching /is_\w+/ are conventionally reserved for bool_constants, but in cpp11 they connote a typedef of enable_if, for example (as.hpp:24):

template <typename T>
using is_integral = typename std::enable_if<
    std::is_integral<T>::value &&
        !std::is_same<typename std::decay<T>::type, bool>::value &&
        !std::is_same<typename std::decay<T>::type, char>::value,
    typename std::decay<T>::type>::type;

The prefix enable_if_ will make it clearer to newcomers that this is an SFINAE helper.

std::map<double, int> as_sexp

Hi,
I am doing a minimal hello world example of using cpp11 in an R package. When I run your example code:

#include <map>
#include "cpp11.hpp"
using namespace cpp11;

[[cpp11::register]]
SEXP table_cpp(doubles x) {
  std::map<double, int> counts;
  int n = x.size();
  for (int i = 0; i < n; i++) {
    counts[x[i]]++;
  }
  return as_sexp(counts);
}

I get the below output. I'm still learning C++, so I'm not 100% sure if this is intended behavior, but I think not.

> cpp11::cpp_register()
> devtools::document()
Updating testcpp11 documentation
Loading testcpp11
Re-compiling testcpp11
─  installing *source* package ‘testcpp11’ ...
   ** using staged installation
   ** libs
   ccache g++-10 -std=gnu++11 -I"/usr/share/R/include" -DNDEBUG  -I"/home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include"   -fpic  -g -O2 -fdebug-prefix-map=/build/r-base-V28x5H/r-base-3.6.3=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g  -c helloCpp.cpp -o helloCpp.o
   helloCpp.cpp: In function ‘SEXPREC* table_cpp(cpp11::doubles)’:
   helloCpp.cpp:74:24: error: no matching function for call to ‘as_sexp(std::map<double, int>&)’
      74 |   return as_sexp(counts);
         |                        ^
   In file included from /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11.hpp:5,
                    from helloCpp.cpp:2:
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:144:13: note: candidate: ‘template<class T, cpp11::is_integral<T>* <anonymous> > SEXPREC* cpp11::as_sexp(T)’
     144 | inline SEXP as_sexp(T from) {
         |             ^~~~~~~
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:144:13: note:   template argument deduction/substitution failed:
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp: In substitution of ‘template<class T> using is_integral = typename std::enable_if<((std::is_integral<_Tp>::value && (! std::is_same<typename std::decay<_Tp>::type, bool>::value)) && (! std::is_same<typename std::decay<_Tp>::type, char>::value)), typename std::decay<_Tp>::type>::type [with T = std::map<double, int>]’:
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:143:41:   required from here
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:25:7: error: no type named ‘type’ in ‘struct std::enable_if<false, std::map<double, int> >’
      25 | using is_integral = typename std::enable_if<
         |       ^~~~~~~~~~~
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:149:13: note: candidate: ‘template<class T, cpp11::is_floating_point_value<T>* <anonymous> > SEXPREC* cpp11::as_sexp(T)’
     149 | inline SEXP as_sexp(T from) {
         |             ^~~~~~~
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:149:13: note:   template argument deduction/substitution failed:
/home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp: In subs   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp: In substitution of ‘template<class T> using is_floating_point_value = typename std::enable_if<std::is_floating_point<_Tp>::value, T>::type [with T = std::map<double, int>]’:
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:148:53:   required from here
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:83:7: error: no type named ‘type’ in ‘struct std::enable_if<false, std::map<double, int> >’
      83 | using is_floating_point_value =
         |       ^~~~~~~~~~~~~~~~~~~~~~~
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:153:13: note: candidate: ‘SEXPREC* cpp11::as_sexp(const string&)’
     153 | inline SEXP as_sexp(const std::string& from) {
         |             ^~~~~~~
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:153:40: note:   no known conversion for argument 1 from ‘std::map<double, int>’ to ‘const string&’ {aka ‘const std::__cxx11::basic_string<char>&’}
     153 | inline SEXP as_sexp(const std::string& from) {
         |                     ~~~~~~~~~~~~~~~~~~~^~~~
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:165:13: note: candidate: ‘template<class T, typename std::enable_if<std::is_same<typename std::decay<_Tp>::type, bool>::value, typename std::decay<_Tp>::type>::type <anonymous> > SEXPREC* cpp11::as_sexp(T)’
     165 | inline SEXP as_sexp(T from) {
         |             ^~~~~~~
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:165:13: note:   template argument deduction/substitution failed:
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:164:36: error: no type named ‘type’ in ‘struct std::enable_if<false, std::map<double, int> >’
     164 | template <typename T, is_bool<T> = false>
         |                                    ^~~~~
/home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:172:13: note: candidate: ‘template<class C, class T, typename std::enable_if<(! std::is_convertible<C, SEXPREC*>::value), typename std::enable_if<((std::is_integral<_Si   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:172:13: note: candidate: ‘template<class C, class T, typename std::enable_if<(! std::is_convertible<C, SEXPREC*>::value), typename std::enable_if<((std::is_integral<_Size>::value && (! std::is_same<typename std::decay<_Tp2>::type, bool>::value)) && (! std::is_same<typename std::decay<_Tp2>::type, char>::value)), typename std::decay<_Tp2>::type>::type>::type* <anonymous> > SEXPREC* cpp11::as_sexp(C)’
     172 | inline SEXP as_sexp(C from) {
         |             ^~~~~~~
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:172:13: note:   template argument deduction/substitution failed:
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:171:60: error: no type named ‘type’ in ‘struct std::enable_if<false, std::pair<const double, int> >’
     171 |                                   is_integral<T>>::type* = nullptr>
         |                                                            ^~~~~~~
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:184:13: note: candidate: ‘SEXPREC* cpp11::as_sexp(std::initializer_list<int>)’
     184 | inline SEXP as_sexp(std::initializer_list<int> from) {
         |             ^~~~~~~
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:184:48: note:   no known conversion for argument 1 from ‘std::map<double, int>’ to ‘std::initializer_list<int>’
     184 | inline SEXP as_sexp(std::initializer_list<int> from) {
         |                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:190:13: note: candidate: ‘template<class C, class T, cpp11::is_floating_point_value<T>* <anonymous> > SEXPREC* cpp11::as_sexp(C)’
     190 | inline SEXP as_sexp(C from) {
         |             ^~~~~~~
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:190:13: note:   template argument deduction/substitution failed:
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp: In substitution of ‘template<class T> using is_floating_point_value = typename std::enable_if<std::is_floating_point<_Tp>::value, T>::type [with T = std::pair<const double, int>]’:
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:189:41:   required from here
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:83:7: error: no type named ‘type’ in ‘struct std::enable_if<false, std::pair<const double, int> >’
      83 | using is_floating_point_value =
         |       ^~~~~~~~~~~~~~~~~~~~~~~
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:202:13: note: candidate: ‘SEXPREC* cpp11::as_sexp(std::initializer_list<double>)’
     202 | inline SEXP as_sexp(std::initializer_list<double> from) {
         |             ^~~~~~~
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:202:51: note:   no known conversion for argument 1 from ‘std::map<double, int>’ to ‘std::initializer_list<double>’
     202 | inline SEXP as_sexp(std::initializer_list<double> from) {
         |                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:207:13: note: candidate: ‘template<class C, class T, cpp11::is_bool<T>* <anonymous> > SEXPREC* cpp11::as_sexp(C)’
     207 | inline SEXP as_sexp(C from) {
         |             ^~~~~~~
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:207:13: note:   template argument deduction/substitution failed:
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp: In substitution of ‘template<class T> using is_bool = typename std::enable_if<std::is_same<typename std::decay<_Tp>::type, bool>::value, typename std::decay<_Tp>::type>::type [with T = std::pair<const double, int>]’:
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:206:74:   required from here
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:160:7: error: no type named ‘type’ in ‘struct std::enable_if<false, std::pair<const double, int> >’
     160 | using is_bool =
         |       ^~~~~~~
/home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:219:13:    /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:219:13: note: candidate: ‘SEXPREC* cpp11::as_sexp(std::initializer_list<bool>)’
     219 | inline SEXP as_sexp(std::initializer_list<bool> from) {
         |             ^~~~~~~
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:219:49: note:   no known conversion for argument 1 from ‘std::map<double, int>’ to ‘std::initializer_list<bool>’
     219 | inline SEXP as_sexp(std::initializer_list<bool> from) {
         |                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:231:13: note: candidate: ‘template<class C, class T, cpp11::is_convertible_to_std_string<T>* <anonymous> > SEXPREC* cpp11::as_sexp(C)’
     231 | inline SEXP as_sexp(C from) {
         |             ^~~~~~~
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:231:13: note:   template argument deduction/substitution failed:
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp: In substitution of ‘template<class T> using is_convertible_to_std_string = typename std::enable_if<(std::is_convertible<typename std::decay<_Tp>::type, std::__cxx11::basic_string<char> >::value && (! std::is_convertible<typename std::decay<_Tp>::type, const char*>::value)), typename std::decay<_Tp>::type>::type [with T = std::pair<const double, int>]’:
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:230:46:   required from here
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:224:7: error: no type named ‘type’ in ‘struct std::enable_if<false, std::pair<const double, int> >’
     224 | using is_convertible_to_std_string = typename std::enable_if<
         |       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:259:13: note: candidate: ‘template<class C, class T, cpp11::is_convertible_to_const_char<T>* <anonymous> > SEXPREC* cpp11::as_sexp(C)’
     259 | inline SEXP as_sexp(C from) {
         |             ^~~~~~~
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:259:13: note:   template argument deduction/substitution failed:
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp: In substitution of ‘template<class T> using is_convertible_to_const_char = typename std::enable_if<(std::is_convertible<typename std::decay<_Tp>::type, const char*>::value && (! std::is_convertible<typename std::decay<_Tp>::type, SEXPREC*>::value)), typename std::decay<_Tp>::type>::type [with T = std::pair<const double, int>]’:
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:258:46:   required from here
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:252:7: error: no type named ‘type’ in ‘struct std::enable_if<false, std::pair<const double, int> >’
     252 | using is_convertible_to_const_char = typename std::enable_if<
         |       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:279:13: note: candidate: ‘SEXPREC* cpp11::as_sexp(std::initializer_list<const char*>)’
     279 | inline SEXP as_sexp(std::initializer_list<const char*> from) {
         |             ^~~~~~~
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:279:56: note:   no known conversion for argument 1 from ‘std::map<double, int>’ to ‘std::initializer_list<const char*>’
     279 | inline SEXP as_sexp(std::initializer_list<const char*> from) {
         |                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:283:13: note: candidate: ‘SEXPREC* cpp11::as_sexp(SEXP)’
     283 | inline SEXP as_sexp(SEXP from) { return from; }
         |             ^~~~~~~
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/as.hpp:283:26: note:   no known conversion for argument 1 from ‘std::map<double, int>’ to ‘SEXP’ {aka ‘SEXPREC*’}
     283 | inline SEXP as_sexp(SEXP from) { return from; }
         |                     ~~~~~^~~~
   In file included from /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/list.hpp:8,
                    from /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/data_frame.hpp:10,
                    from /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11.hpp:7,
                    from helloCpp.cpp:2:
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/r_string.hpp:58:13: note: candidate: ‘template<class T, cpp11::is_convertible_to_cpp11_string<T>* <anonymous> > SEXPREC* cpp11::as_sexp(T)’
      58 | inline SEXP as_sexp(T from) {
         |             ^~~~~~~
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/r_string.hpp:58:13: note:   template argument deduction/substitution failed:
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/r_string.hpp: In substitution of ‘template<class T> using is_convertible_to_cpp11_string = typename std::enable_if<(std::is_convertible<T, cpp11::r_string>::value && (! std::is_convertible<T, const char*>::value)), T>::type [with T = std::map<double, int>]’:
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/r_string.hpp:57:60:   required from here
   /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/r_string.hpp:52:7: error: no type named ‘type’ in ‘struct std::enable_if<false, std::map<double, int> >’
      52 | using is_convertible_to_cpp11_string =
         |       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   /usr/lib/R/etc/Makeconf:177: recipe for target 'helloCpp.o' failed
   make: *** [helloCpp.o] Error 1
   ERROR: compilation failed for package ‘testcpp11’
─  removing ‘/tmp/Rtmp6dP72C/devtools_install_1f3d6b99a0e5/testcpp11’
Error in (function (command = NULL, args = character(), error_on_status = TRUE,  : 
  System command 'R' failed, exit status: 1, stdout + stderr (last 10 lines):
E> /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/r_string.hpp:58:13: note:   template argument deduction/substitution failed:
E> /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/r_string.hpp: In substitution of ‘template<class T> using is_convertible_to_cpp11_string = typename std::enable_if<(std::is_convertible<T, cpp11::r_string>::value && (! std::is_convertible<T, const char*>::value)), T>::type [with T = std::map<double, int>]’:
E> /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/r_string.hpp:57:60:   required from here
E> /home/mads/R/x86_64-pc-linux-gnu-library/3.6/cpp11/include/cpp11/r_string.hpp:52:7: error: no type named ‘type’ in ‘struct std::enable_if<false, std::map<double, int> >’
E>    52 | using is_convertible_to_cpp11_string =
E>       |       ^~~~~~~~~~~~~~~~~~~~~~~~
[...]

> sessionInfo()
R version 3.6.3 (2020-02-29)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 18.04.4 LTS

Matrix products: default
BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.7.1
LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.7.1

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C

Permissive handling of integers in cpp11::integers

At the moment, coersion from an R numeric scalar to an int works nicely - doubles are converted to integers if they are representable as integers without truncation of the decimal part. However, the same is not true of a vector of numeric values into cpp11::integers:

cpp11::cpp_source(
  code = c(
    "#include <cpp11.hpp>",
    "[[cpp11::register]]",
    "void test(int x, cpp11::integers y) {",
    "}"))
test(1L, 1L) # works, as expected
test(1, 1L)  # works, due to the double -> int conversion
test(1L, 1)  # fails with error "Invalid input type, expected 'integer' actual 'double'"

The same problem impacts passing a vector of integers to a function expecting doubles:

cpp11::cpp_source(
  code = c(
    "#include <cpp11.hpp>",
    "[[cpp11::register]]",
    "void test2(cpp11::doubles y) {",
    "}"))
test2(seq_len(4))
#> Error in test2(seq_len(4)) : 
#>   Invalid input type, expected 'double' actual 'integer'

It would be nice if it is possible to relax this as practically this requires additional wrappers to the be added in either the C++ or the R code, especially as the name of the problematic variable can't be easily found from the error message.

const T& as input

cpp11::cpp_function('int twice(const int& x) {
  return x * 2;
}', quiet = FALSE)
#> clang++ -mmacosx-version-min=10.13 -std=gnu++11 -I"/Library/Frameworks/R.framework/Resources/include" -DNDEBUG -I/Users/romainfrancois/.R/library/4.0/cpp11/include  -I/usr/local/include   -fPIC  -Wall -O3 -Wall -Wimplicit-int-float-conversion -c /private/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T/RtmpRFFnOt/filedea24914c969/src/code_0.cpp -o /private/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T/RtmpRFFnOt/filedea24914c969/src/code_0.o
#> clang++ -mmacosx-version-min=10.13 -std=gnu++11 -I"/Library/Frameworks/R.framework/Resources/include" -DNDEBUG -I/Users/romainfrancois/.R/library/4.0/cpp11/include  -I/usr/local/include   -fPIC  -Wall -O3 -Wall -Wimplicit-int-float-conversion -c /private/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T/RtmpRFFnOt/filedea24914c969/src/cpp11.cpp -o /private/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T/RtmpRFFnOt/filedea24914c969/src/cpp11.o
#> /private/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T/RtmpRFFnOt/filedea24914c969/src/cpp11.cpp:7:47: error: no matching function for call to 'as_cpp'
#>     return cpp11::as_sexp(twice(cpp11::unmove(cpp11::as_cpp<const int&>(x))));
#>                                               ^~~~~~~~~~~~~~~~~~~~~~~~~
#> /Users/romainfrancois/.R/library/4.0/cpp11/include/cpp11/as.hpp:20:31: note: candidate template ignored: requirement 'std::is_constructible<const int &, SEXPREC *>::value' was not satisfied [with T = const int &]
#> is_constructible_from_sexp<T> as_cpp(SEXP from) {
#>                               ^
#> /Users/romainfrancois/.R/library/4.0/cpp11/include/cpp11/as.hpp:46:16: note: candidate template ignored: requirement 'std::is_integral<const int &>::value' was not satisfied [with T = const int &]
#> is_integral<T> as_cpp(SEXP from) {
#>                ^
#> /Users/romainfrancois/.R/library/4.0/cpp11/include/cpp11/as.hpp:70:15: note: candidate template ignored: requirement 'std::is_same<int, bool>::value' was not satisfied [with T = const int &]
#> is_logical<T> as_cpp(SEXP from) {
#>               ^
#> /Users/romainfrancois/.R/library/4.0/cpp11/include/cpp11/as.hpp:87:28: note: candidate template ignored: requirement 'std::is_floating_point<const int &>::value' was not satisfied [with T = const int &]
#> is_floating_point_value<T> as_cpp(SEXP from) {
#>                            ^
#> /Users/romainfrancois/.R/library/4.0/cpp11/include/cpp11/as.hpp:109:12: note: candidate template ignored: requirement 'std::is_same<int, char>::value' was not satisfied [with T = const int &]
#> is_char<T> as_cpp(SEXP from) {
#>            ^
#> /Users/romainfrancois/.R/library/4.0/cpp11/include/cpp11/as.hpp:129:37: note: candidate template ignored: requirement 'std::is_constructible<int, const char *>::value' was not satisfied [with T = const int &]
#> is_constructible_from_const_char<T> as_cpp(SEXP from) {
#>                                     ^
#> /Users/romainfrancois/.R/library/4.0/cpp11/include/cpp11/r_vector.hpp:933:43: note: candidate template ignored: substitution failure [with C = const int &]: 'std::__1::decay<const int &>::type' (aka 'int') is not a class, namespace, or enumeration
#> is_container_but_not_sexp_or_string<C, T> as_cpp(SEXP from) {
#>                                           ^
#> /Users/romainfrancois/.R/library/4.0/cpp11/include/cpp11/r_vector.hpp:946:28: note: candidate template ignored: substitution failure [with C = const int &]: 'std::__1::decay<const int &>::type' (aka 'int') is not a class, namespace, or enumeration
#> is_vector_of_strings<C, T> as_cpp(SEXP from) {
#>                            ^
#> 1 error generated.
#> make: *** [/private/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T/RtmpRFFnOt/filedea24914c969/src/cpp11.o] Error 1
#> Error in dyn.load(shared_lib, local = TRUE, now = TRUE): unable to load shared object '/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T//RtmpRFFnOt/filedea24914c969/src/code_0.so':
#>   dlopen(/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T//RtmpRFFnOt/filedea24914c969/src/code_0.so, 6): image not found

Created on 2020-07-21 by the reprex package (v0.3.0.9001)

Rcpp deals with this with the extra layer of indirection given by the various Rcpp::traits::input_parameter<> classes:

Rcpp::cppFunction('int twice(const int& x) {
  return x * 2;
}', verbose = TRUE)
#> 
#> Generated code for function definition: 
#> --------------------------------------------------------
#> 
#> #include <Rcpp.h>
#> 
#> using namespace Rcpp;
#> 
#> // [[Rcpp::export]]
#> int twice(const int& x) {
#>   return x * 2;
#> }
#> 
#> Generated extern "C" functions 
#> --------------------------------------------------------
#> 
#> 
#> #include <Rcpp.h>
#> // twice
#> int twice(const int& x);
#> RcppExport SEXP sourceCpp_1_twice(SEXP xSEXP) {
#> BEGIN_RCPP
#>     Rcpp::RObject rcpp_result_gen;
#>     Rcpp::RNGScope rcpp_rngScope_gen;
#>     Rcpp::traits::input_parameter< const int& >::type x(xSEXP);
#>     rcpp_result_gen = Rcpp::wrap(twice(x));
#>     return rcpp_result_gen;
#> END_RCPP
#> }
#> 
#> Generated R functions 
#> -------------------------------------------------------
#> 
#> `.sourceCpp_1_DLLInfo` <- dyn.load('/private/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T/Rtmp5bfOwE/sourceCpp-x86_64-apple-darwin17.0-1.0.5/sourcecpp_df104719c3e9/sourceCpp_2.so')
#> 
#> twice <- Rcpp:::sourceCppFunction(function(x) {}, FALSE, `.sourceCpp_1_DLLInfo`, 'sourceCpp_1_twice')
#> 
#> rm(`.sourceCpp_1_DLLInfo`)
#> 
#> Building shared library
#> --------------------------------------------------------
#> 
#> DIR: /private/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T/Rtmp5bfOwE/sourceCpp-x86_64-apple-darwin17.0-1.0.5/sourcecpp_df104719c3e9
#> 
#> /Library/Frameworks/R.framework/Resources/bin/R CMD SHLIB -o 'sourceCpp_2.so' 'filedf107957208b.cpp'
twice(21L)
#> [1] 42

Created on 2020-07-21 by the reprex package (v0.3.0.9001)

In that case Rcpp::traits::input_parameter< const int& > holds an int and exposes it as a const int&, and this allows for extensions, e.g. in arrow many of the functions take const std::shared_ptr<T>& and arrow has a custom input_parameter<const std::shared_ptr<T>&> that knows how to extract the information from the R6 object that is passed in.

I don't think it can be done in cpp11 with the current code generation.

Name clash with `std::vector`

I find it a bit confusing to read code with a templated class called vector that is not std::vector. How about cpp11::r_vector<>?

cpp code garbled in "Get started with cpp11" vignette online

Following along with the "Get started with cpp11" vignette (https://cpp11.r-lib.org/articles/cpp11.html), the cpp code seems to be getting garbled when the vignette is produced. For example, the vignette example lines 117-121 (https://github.com/r-lib/cpp11/blob/master/vignettes/cpp11.Rmd)

int one() {
  return 1;
}

is rendered in the vignette (https://cpp11.r-lib.org/articles/cpp11.html#no-inputs-scalar-output-1) as

cpp_function('int one() {
  return 1;
}'p_function('int one() {
  return 1;
}')

Somehow the code isn't parsing correctly such that part of the code is pasted into itself. This might be a pkgdown issue, because my local copy of the vignette looks fine.

Calling names() on vectors without names

Not entirely sure if it should return R_NilValue or an empty character vector, probably the latter.

Something like this should reproduce it.

cpp11::writable::doubles x;
x.names()

RNG Scope?

Any thoughts on ensuring the correct RNG functionality with the Rmath library?

For instance, if we create a cpp11 function that interfaces with Rf_norm():

cpp11::cpp_source(
    code = '
#include "cpp11/doubles.hpp"
#include "R.h"
#include "Rmath.h"

[[cpp11::register]]
double rng_cpp() {
  double x = Rf_rnorm(0, 1);
  return x;
}

[[cpp11::register]]
double rng_explicit_state_cpp() {
  GetRNGstate();
  double x = Rf_rnorm(0, 1);
  PutRNGstate();
  return x;
}', quiet = FALSE)

The subsequent running of the versions between C++ and R produce the same result without a seed being re-set.

set.seed(3161611)
rng_cpp()
#> [1] -0.9325398
rnorm(1)
#> [1] -0.9325398

Under the second function with an explicit Get/Put state call the desired results are achieved:

set.seed(3161611)
rng_explicit_state_cpp()
#> [1] -0.9325398
rnorm(1)
#> [1] 0.8282708

From looking at exported code it seems like there is no wrapping of C++ calls with GetRNGstate()/PutRNGstate(). Perhaps this should be added to the converting documents or addressed during code generation?

avoid potential null deref in as_cpp

Looking here:

if (Rf_isString(from)) {
if (Rf_xlength(from) == 1) {
const char* c_p = nullptr;
unwind_protect([&] { c_p = Rf_translateCharUTF8(STRING_ELT(from, 0)); });
return c_p[0];
}
}

If an error occurs during translation, c_p will remain as a nullptr and then the attempt to access the zero-th element will likely crash.

Difficulty understanding the protection benchmarks

I've read this a few times and I confess I cannot make heads or tails of the results. Perhaps I'm just reading it wrong. I thought I'd mention it incase there is a bug. I'm usually adept at interpreting plots, so if its correct, perhaps there is another way to present the data?

LinkingTo directive with cpp_source?

Is there an equivalent to // [[Rcpp::depends()]] for cpp11? Trying to make a MRE (so not in a package) and need to link with another package for that one bit of code.

enum with underlying type: char

cpp11::cpp_source(code = '
#include <cpp11.hpp>

enum class Color : char { red, green = 20, blue };

[[cpp11::register]]
void fun(SEXP value) {
  cpp11::as_cpp<Color>(value);
}

', quiet = FALSE)
#> clang++ -mmacosx-version-min=10.13 -std=gnu++11 -I"/Library/Frameworks/R.framework/Resources/include" -DNDEBUG -I/Users/romainfrancois/.R/library/4.0/cpp11/include  -I/usr/local/include   -fPIC  -Wall -O3 -Wall -Wimplicit-int-float-conversion -c /private/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T/RtmpzSpGdd/filef6b4538517d5/src/code_0.cpp -o /private/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T/RtmpzSpGdd/filef6b4538517d5/src/code_0.o
#> In file included from /private/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T/RtmpzSpGdd/filef6b4538517d5/src/code_0.cpp:2:
#> In file included from /Users/romainfrancois/.R/library/4.0/cpp11/include/cpp11.hpp:5:
#> /Users/romainfrancois/.R/library/4.0/cpp11/include/cpp11/as.hpp:80:27: error: call to function 'as_cpp' that is neither visible in the template definition nor found by argument-dependent lookup
#>     return static_cast<E>(as_cpp<typename std::underlying_type<E>::type>(from));
#>                           ^
#> /private/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T/RtmpzSpGdd/filef6b4538517d5/src/code_0.cpp:8:10: note: in instantiation of function template specialization 'cpp11::as_cpp<Color>' requested here
#>   cpp11::as_cpp<Color>(value);
#>          ^
#> /Users/romainfrancois/.R/library/4.0/cpp11/include/cpp11/as.hpp:143:12: note: 'as_cpp' should be declared prior to the call site or in the global namespace
#> is_char<T> as_cpp(SEXP from) {
#>            ^
#> 1 error generated.
#> make: *** [/private/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T/RtmpzSpGdd/filef6b4538517d5/src/code_0.o] Error 1
#> Error in dyn.load(shared_lib, local = TRUE, now = TRUE): unable to load shared object '/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T//RtmpzSpGdd/filef6b4538517d5/src/code_0.so':
#>   dlopen(/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T//RtmpzSpGdd/filef6b4538517d5/src/code_0.so, 6): image not found
fun(0L)
#> Error in .Call("_code_0_fun", value, PACKAGE = "code_0"): "_code_0_fun" not available for .Call() for package "code_0"

Created on 2020-08-05 by the reprex package (v0.3.0.9001)

gcc 4.8.5 compatibility

Hi,

I'm trying to install another package (tidyr) on CentOS7 which is apparently trying to use cpp11 library.
It throws multiple errors:

g++ -std=gnu++11 -I"/software/R-3.6.2/include" -DNDEBUG  -I"/data/software/R-3.6.2/library/cpp11/include" -I/usr/include -I/software/CLAPACK-3.2.1/INCLUDE -I/software/gsl-2.6/include -I/software/proj-6.0.0/include/proj -I/software/hdf5-1.10.4/include/  -fpic  -g -O2  -c cpp11.cpp -o cpp11.o
In file included from /data/software/R-3.6.2/library/cpp11/include/cpp11/as.hpp:8:0,
                 from /data/software/R-3.6.2/library/cpp11/include/cpp11.hpp:5,
                 from /data/software/R-3.6.2/library/cpp11/include/cpp11/declarations.hpp:8,
                 from cpp11.cpp:4:
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp: In lambda function:
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:47: error: parameter packs not expanded with ‘...’:
       return unwind_protect([&] { return ptr_(a...); });
                                               ^
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:47: note:         ‘a’
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:48: error: expansion pattern ‘a’ contains no argument packs
       return unwind_protect([&] { return ptr_(a...); });
                                                ^
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp: In lambda function:
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:199:38: error: parameter packs not expanded with ‘...’:
   unwind_protect([&] { Rf_error(fmt, args...); });
                                      ^
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:199:38: note:         ‘args’
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:199:42: error: expansion pattern ‘args’ contains no argument packs
   unwind_protect([&] { Rf_error(fmt, args...); });
                                          ^
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp: In lambda function:
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:206:46: error: parameter packs not expanded with ‘...’:
   unwind_protect([&] { Rf_error(fmt.c_str(), args...); });
                                              ^
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:206:46: note:         ‘args’
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:206:50: error: expansion pattern ‘args’ contains no argument packs
   unwind_protect([&] { Rf_error(fmt.c_str(), args...); });
                                                  ^
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp: In instantiation of ‘struct cpp11::protect::function<F>::operator()(A ...) const [with A = {}; F = void(); decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) = void]::__lambda2’:
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:55:   required from ‘decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) cpp11::protect::function<F>::operator()(A ...) const [with A = {}; F = void(); decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) = void]’
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:195:65:   required from here
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:47: error: using invalid field ‘cpp11::protect::function<F>::operator()(A ...) const::__lambda2::__a’
       return unwind_protect([&] { return ptr_(a...); });
                                               ^
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp: In instantiation of ‘decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) cpp11::protect::function<F>::operator()(A ...) const [with A = {}; F = void(); decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) = void]’:
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:195:65:   required from here
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:55: error: return-statement with a value, in function returning 'void' [-fpermissive]
       return unwind_protect([&] { return ptr_(a...); });
                                                       ^
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp: In instantiation of ‘struct cpp11::protect::function<F>::operator()(A ...) const [with A = {const char*, cetype_t}; F = SEXPREC*(const char*, cetype_t); decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) = SEXPREC*]::__lambda2’:
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:55:   required from ‘decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) cpp11::protect::function<F>::operator()(A ...) const [with A = {const char*, cetype_t}; F = SEXPREC*(const char*, cetype_t); decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) = SEXPREC*]’
/data/software/R-3.6.2/library/cpp11/include/cpp11/r_string.hpp:16:69:   required from here
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:47: error: using invalid field ‘cpp11::protect::function<F>::operator()(A ...) const::__lambda2::__a’
       return unwind_protect([&] { return ptr_(a...); });
                                               ^
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp: In instantiation of ‘struct cpp11::protect::function<F>::operator()(A ...) const [with A = {int, long unsigned int}; F = SEXPREC*(unsigned int, long int); decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) = SEXPREC*]::__lambda2’:
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:55:   required from ‘decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) cpp11::protect::function<F>::operator()(A ...) const [with A = {int, long unsigned int}; F = SEXPREC*(unsigned int, long int); decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) = SEXPREC*]’
/data/software/R-3.6.2/library/cpp11/include/cpp11/list.hpp:75:67:   required from here
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:47: error: using invalid field ‘cpp11::protect::function<F>::operator()(A ...) const::__lambda2::__a’
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp: In instantiation of ‘struct cpp11::protect::function<F>::operator()(A ...) const [with A = {int, long int}; F = SEXPREC*(unsigned int, long int); decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) = SEXPREC*]::__lambda2’:
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:55:   required from ‘decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) cpp11::protect::function<F>::operator()(A ...) const [with A = {int, long int}; F = SEXPREC*(unsigned int, long int); decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) = SEXPREC*]’
/data/software/R-3.6.2/library/cpp11/include/cpp11/list.hpp:107:74:   required from here
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:47: error: using invalid field ‘cpp11::protect::function<F>::operator()(A ...) const::__lambda2::__a’
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp: In instantiation of ‘struct cpp11::protect::function<F>::operator()(A ...) const [with A = {SEXPREC*, long int}; F = SEXPREC*(SEXPREC*, long int); decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) = SEXPREC*]::__lambda2’:
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:55:   required from ‘decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) cpp11::protect::function<F>::operator()(A ...) const [with A = {SEXPREC*, long int}; F = SEXPREC*(SEXPREC*, long int); decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) = SEXPREC*]’
/data/software/R-3.6.2/library/cpp11/include/cpp11/list.hpp:108:73:   required from here
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:47: error: using invalid field ‘cpp11::protect::function<F>::operator()(A ...) const::__lambda2::__a’
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp: In instantiation of ‘struct cpp11::protect::function<F>::operator()(A ...) const [with A = {const char*}; F = SEXPREC*(const char*); decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) = SEXPREC*]::__lambda2’:
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:55:   required from ‘decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) cpp11::protect::function<F>::operator()(A ...) const [with A = {const char*}; F = SEXPREC*(const char*); decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) = SEXPREC*]’
/data/software/R-3.6.2/library/cpp11/include/cpp11/function.hpp:59:50:   required from here
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:47: error: using invalid field ‘cpp11::protect::function<F>::operator()(A ...) const::__lambda2::__a’
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp: In instantiation of ‘struct cpp11::protect::function<F>::operator()(A ...) const [with A = {SEXPREC*, SEXPREC*}; F = SEXPREC*(SEXPREC*, SEXPREC*); decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) = SEXPREC*]::__lambda2’:
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:55:   required from ‘decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) cpp11::protect::function<F>::operator()(A ...) const [with A = {SEXPREC*, SEXPREC*}; F = SEXPREC*(SEXPREC*, SEXPREC*); decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) = SEXPREC*]’
/data/software/R-3.6.2/library/cpp11/include/cpp11/function.hpp:59:58:   required from here
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:47: error: using invalid field ‘cpp11::protect::function<F>::operator()(A ...) const::__lambda2::__a’
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp: In instantiation of ‘struct cpp11::protect::function<F>::operator()(A ...) const [with A = {SEXPREC*, cpp11::sexp}; F = SEXPREC*(SEXPREC*, SEXPREC*); decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) = SEXPREC*]::__lambda2’:
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:55:   required from ‘decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) cpp11::protect::function<F>::operator()(A ...) const [with A = {SEXPREC*, cpp11::sexp}; F = SEXPREC*(SEXPREC*, SEXPREC*); decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) = SEXPREC*]’
/data/software/R-3.6.2/library/cpp11/include/cpp11/function.hpp:69:66:   required from here
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:47: error: using invalid field ‘cpp11::protect::function<F>::operator()(A ...) const::__lambda2::__a’
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp: In instantiation of ‘struct cpp11::protect::function<F>::operator()(A ...) const [with A = {SEXPREC*, SEXPREC*, Rboolean}; F = SEXPREC*(SEXPREC*, SEXPREC*, Rboolean); decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) = SEXPREC*]::__lambda2’:
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:55:   required from ‘decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) cpp11::protect::function<F>::operator()(A ...) const [with A = {SEXPREC*, SEXPREC*, Rboolean}; F = SEXPREC*(SEXPREC*, SEXPREC*, Rboolean); decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) = SEXPREC*]’
/data/software/R-3.6.2/library/cpp11/include/cpp11/environment.hpp:36:81:   required from here
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:47: error: using invalid field ‘cpp11::protect::function<F>::operator()(A ...) const::__lambda2::__a’
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp: In instantiation of ‘struct cpp11::protect::function<F>::operator()(A ...) const [with A = {cpp11::sexp, SEXPREC*, Rboolean}; F = SEXPREC*(SEXPREC*, SEXPREC*, Rboolean); decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) = SEXPREC*]::__lambda2’:
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:55:   required from ‘decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) cpp11::protect::function<F>::operator()(A ...) const [with A = {cpp11::sexp, SEXPREC*, Rboolean}; F = SEXPREC*(SEXPREC*, SEXPREC*, Rboolean); decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) = SEXPREC*]’
/data/software/R-3.6.2/library/cpp11/include/cpp11/environment.hpp:47:58:   required from here
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:47: error: using invalid field ‘cpp11::protect::function<F>::operator()(A ...) const::__lambda2::__a’
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp: In instantiation of ‘struct cpp11::protect::function<F>::operator()(A ...) const [with A = {int, int}; F = SEXPREC*(unsigned int, long int); decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) = SEXPREC*]::__lambda2’:
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:55:   required from ‘decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) cpp11::protect::function<F>::operator()(A ...) const [with A = {int, int}; F = SEXPREC*(unsigned int, long int); decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) = SEXPREC*]’
/data/software/R-3.6.2/library/cpp11/include/cpp11/strings.hpp:71:70:   required from here
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:47: error: using invalid field ‘cpp11::protect::function<F>::operator()(A ...) const::__lambda2::__a’
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp: In instantiation of ‘struct cpp11::protect::function<F>::operator()(A ...) const [with A = {SEXPREC*}; F = SEXPREC*(SEXPREC*); decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) = SEXPREC*]::__lambda2’:
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:55:   required from ‘decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) cpp11::protect::function<F>::operator()(A ...) const [with A = {SEXPREC*}; F = SEXPREC*(SEXPREC*); decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) = SEXPREC*]’
/data/software/R-3.6.2/library/cpp11/include/cpp11/strings.hpp:73:45:   required from here
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:47: error: using invalid field ‘cpp11::protect::function<F>::operator()(A ...) const::__lambda2::__a’
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp: In instantiation of ‘struct cpp11::protect::function<F>::operator()(A ...) const [with A = {cpp11::sexp, SEXPREC*}; F = SEXPREC*(SEXPREC*, SEXPREC*); decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) = SEXPREC*]::__lambda2’:
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:55:   required from ‘decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) cpp11::protect::function<F>::operator()(A ...) const [with A = {cpp11::sexp, SEXPREC*}; F = SEXPREC*(SEXPREC*, SEXPREC*); decltype (declval<F*>()(cpp11::protect::function::operator()::a ...)) = SEXPREC*]’
/data/software/R-3.6.2/library/cpp11/include/cpp11/function.hpp:27:43:   required from ‘cpp11::sexp cpp11::function::operator()(Args&& ...) const [with Args = {SEXPREC*&, cpp11::named_arg&}]’
/data/software/R-3.6.2/library/cpp11/include/cpp11/environment.hpp:60:35:   required from here
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:183:47: error: using invalid field ‘cpp11::protect::function<F>::operator()(A ...) const::__lambda2::__a’
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp: In instantiation of ‘struct cpp11::stop(const char*, Args ...) [with Args = {}]::__lambda3’:
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:199:49:   required from ‘void cpp11::stop(const char*, Args ...) [with Args = {}]’
/data/software/R-3.6.2/library/cpp11/include/cpp11/as.hpp:98:39:   required from ‘cpp11::is_logical<T> cpp11::as_cpp(SEXP) [with T = bool; cpp11::is_logical<T> = bool; SEXP = SEXPREC*]’
cpp11.cpp:24:452:   required from here
/data/software/R-3.6.2/library/cpp11/include/cpp11/protect.hpp:199:38: error: using invalid field ‘cpp11::stop(const char*, Args ...)::__lambda3::__args’
   unwind_protect([&] { Rf_error(fmt, args...); });
                                      ^
make: *** [cpp11.o] Error 1
ERROR: compilation failed for package ‘tidyr’

Apparently the compilation errors are coming from several hpp files.
If you have any idea of a simple flag to add to make it work? Or if I need to recompile the cpp11 library with specific flags.

Thanks in advance

C++11?

What's the motivation for starting at C++11 now that C++17 (and goodies like if constexpr) is available on all platforms?

writable::logicals::proxy = bool

cpp11::cpp_function('
cpp11::writable::logicals bools(){ 
  cpp11::writable::logicals x(1);
  x[0] = true;
  return x;
  } 
', quiet = FALSE)
#> clang++ -mmacosx-version-min=10.13 -std=gnu++11 -I"/Library/Frameworks/R.framework/Resources/include" -DNDEBUG -I/Users/romainfrancois/.R/library/4.0/cpp11/include  -I/usr/local/include   -fPIC  -Wall -O3 -Wall -Wimplicit-int-float-conversion -c /private/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T/Rtmp4AL6sg/file3d916be862b1/src/code_0.cpp -o /private/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T/Rtmp4AL6sg/file3d916be862b1/src/code_0.o
#> /private/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T/Rtmp4AL6sg/file3d916be862b1/src/code_0.cpp:8:8: error: no viable overloaded '='
#>   x[0] = true;
#>   ~~~~ ^ ~~~~
#> /Users/romainfrancois/.R/library/4.0/cpp11/include/cpp11/r_vector.hpp:216:9: note: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'bool' to 'const cpp11::writable::r_vector<Rboolean>::proxy' for 1st argument
#>   class proxy {
#>         ^
#> /Users/romainfrancois/.R/library/4.0/cpp11/include/cpp11/logicals.hpp:51:71: note: candidate function not viable: no known conversion from 'bool' to 'const Rboolean' for 1st argument
#> inline typename r_vector<Rboolean>::proxy& r_vector<Rboolean>::proxy::operator=(
#>                                                                       ^
#> 1 error generated.
#> make: *** [/private/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T/Rtmp4AL6sg/file3d916be862b1/src/code_0.o] Error 1
#> Error in dyn.load(shared_lib, local = TRUE, now = TRUE): unable to load shared object '/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T//Rtmp4AL6sg/file3d916be862b1/src/code_0.so':
#>   dlopen(/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T//Rtmp4AL6sg/file3d916be862b1/src/code_0.so, 6): image not found
bools()
#> Error in .Call("_code_0_bools", PACKAGE = "code_0"): "_code_0_bools" not available for .Call() for package "code_0"

Created on 2020-07-24 by the reprex package (v0.3.0.9001)

We can do this 👇, but I believe it still would be useful to allow it.

cpp11::cpp_function('
cpp11::writable::logicals bools(){ 
  cpp11::writable::logicals x(1);
  x[0] = true ? TRUE : FALSE;
  return x;
  } 
', quiet = FALSE)
#> clang++ -mmacosx-version-min=10.13 -std=gnu++11 -I"/Library/Frameworks/R.framework/Resources/include" -DNDEBUG -I/Users/romainfrancois/.R/library/4.0/cpp11/include  -I/usr/local/include   -fPIC  -Wall -O3 -Wall -Wimplicit-int-float-conversion -c /private/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T/RtmpFsTE6w/file3dd0596b29c2/src/code_0.cpp -o /private/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T/RtmpFsTE6w/file3dd0596b29c2/src/code_0.o
#> clang++ -mmacosx-version-min=10.13 -std=gnu++11 -I"/Library/Frameworks/R.framework/Resources/include" -DNDEBUG -I/Users/romainfrancois/.R/library/4.0/cpp11/include  -I/usr/local/include   -fPIC  -Wall -O3 -Wall -Wimplicit-int-float-conversion -c /private/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T/RtmpFsTE6w/file3dd0596b29c2/src/cpp11.cpp -o /private/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T/RtmpFsTE6w/file3dd0596b29c2/src/cpp11.o
#> clang++ -mmacosx-version-min=10.13 -std=gnu++11 -dynamiclib -Wl,-headerpad_max_install_names -undefined dynamic_lookup -single_module -multiply_defined suppress -L/Library/Frameworks/R.framework/Resources/lib -L/usr/local/lib -o /private/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T/RtmpFsTE6w/file3dd0596b29c2/src/code_0.so /private/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T/RtmpFsTE6w/file3dd0596b29c2/src/code_0.o /private/var/folders/4b/hn4fq98s6810s4ccv2f9hm2h0000gn/T/RtmpFsTE6w/file3dd0596b29c2/src/cpp11.o -F/Library/Frameworks/R.framework/.. -framework R -Wl,-framework -Wl,CoreFoundation
bools()
#> [1] TRUE

Created on 2020-07-24 by the reprex package (v0.3.0.9001)

Support pkg_types.h

Rcpp supports a pkg_types.h file which allows you to declare types used in your package, which can then be used in the cpp11-exports.cpp file.

We should probably do the same, it is a good way to support custom types and headers.

unwind_protect and safe[] can only be used for SEXP or void return

This introduces unnecessary boilerplate when using a function like Rf_translateCharUTF8 which returns const char*:

const char* c_p = nullptr;
unwind_protect([&] { c_p = Rf_translateCharUTF8(STRING_ELT(from, 0)); });
return c_p[0];

It would be fairly straightforward to extend these to allow:

      return unwind_protect([&] { return Rf_translateCharUTF8(STRING_ELT(from, 0)); })[0];

Or even (provided STRING_ELT doesn't require protection):

      return safe[Rf_translateCharUTF8](STRING_ELT(from, 0))[0];

Catch all exception handler

First, thanks for this package! I've longed for a lean R to C++ interface for quite awhile.

It looks like the END_CPP11 macro lacks a catch-all exception handler. I was using a Boost library and wondering why I was getting aborts (it was not using std::exception). Was a catch(...){} block intentionally omitted?

cpp11::cpp_function('void test() { throw; }')
test() # abort

On OSX

R version 3.6.3 (2020-02-29) -- "Holding the Windsock"
Copyright (C) 2020 The R Foundation for Statistical Computing
Platform: x86_64-apple-darwin15.6.0 (64-bit)

R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.

  Natural language support but running in an English locale

R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.

Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.

> cpp11::cpp_function('void test() { throw; }')
> test() # abort
libc++abi.dylib: terminating
zsh: abort      R

[Question] Return NA_character

What correct way to return NA_character?

> cpp_eval('cpp11::r_string(NA_STRING)')
[1] "NA"
> cpp_eval('cpp11::writable::strings(NA_STRING)')
[1] NA
> cpp_eval('cpp11::writable::strings({NA_STRING})')
[1] "NA"
> cpp_eval('cpp11::writable::strings({NA_STRING, "text"})')
[1] "NA"   "text"

Most recent function is faster

I was doing some benchmarking and got some strange results.

I think I got it minimal enough now. It appears that any function when being defined adds calling time to any previous functions.

library(cpp11)

cpp_function("void void_a() {}")
cpp_function("void void_b() {}")

bm <- bench::mark(
  void_a(),
  void_b()
)

plot(bm)
#> Loading required namespace: tidyr

cpp_function("void void_b() {}")
cpp_function("void void_a() {}")

bm <- bench::mark(
  void_a(),
  void_b()
)

plot(bm)

Created on 2020-06-17 by the reprex package (v0.3.0)

library(cpp11)

cpp_function("void void_a() {}")
cpp_function("void void_b() {}")
cpp_function("void void_c() {}")
cpp_function("void void_d() {}")
cpp_function("void void_e() {}")

bm <- bench::mark(
  void_a(),
  void_b(),
  void_c(),
  void_d(),
  void_e()
)

plot(bm)
#> Loading required namespace: tidyr

Created on 2020-06-17 by the reprex package (v0.3.0)

#pragma once is non-standard

Although it's probably supported on all compilers used on CRAN (even Solaris IIUC) it's probably better to stick to the standard include guards.

Avoid trailing whitespace in generated files

This package is very exciting - I'm exploring using it on a couple of projects at the moment. I've noticed that the cpp11.cpp and cpp11.R files that are created have a trailing blank line. I would create a PR to fix it, but this looks intentional (

and ) - is there a reason for this or could this be dropped?

Also, how stable is the API likely to be? I recognise this is very much a work in progress, but also clearly something you've been thinking about for a bit.

Need modify in-place

Sometimes for best performance, in-place modification is really needed. For example, if one needs a cpp11 function that in-place sorts an R vector without making a copy just like std::sort, or a cpp11 functions that performs in-place winsorization for speed (because it knows that the input vector is only intermediate and could be changed to avoid more allocation). I'm wondering if there's a decent way to do so without using DATAPTR from R C API?

A major point of using Rcpp is for speed but I'm wondering if modifying an R vector by reference is completely prohibited in cpp11?

nrow and ncol doesn't work for matrix class

library(cpp11)

x <- matrix(runif(4), nrow = 2)

cpp_function("int get_nrow(cpp11::doubles_matrix x) {
  int res = x.nrow();
  
  return(res);
}")

get_nrow(x)
#> [1] 2076180480

cpp_function("int get_ncol(cpp11::doubles_matrix x) {
  int res = x.ncol();
  
  return(res);
}")

get_ncol(x)
#> [1] 0

Created on 2020-06-16 by the reprex package (v0.3.0)

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.