Skip to content

Commit c52b01b

Browse files
authored
nClass copying (#97)
* Provide copying into compiled nClass by generic list or env * avoid use of template specializations within class definition. fix set_all_values tests.
1 parent 5978d82 commit c52b01b

File tree

9 files changed

+359
-931
lines changed

9 files changed

+359
-931
lines changed

nCompiler/R/NC_SimpleInterface.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ value <- function(obj, name) {
4343
}
4444

4545
#' @export
46-
`value<-` <- function(obj, name, value) {
46+
`value<-` <- function(obj, name = NULL, value) {
4747
if(inherits(obj, "CnClass"))
4848
obj <- obj$private$CppObj
4949
DLLenv <- get_DLLenv(obj)

nCompiler/R/cppDefs_R_interface_calls.R

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,15 @@ global_R_interface_cppDef <-
2727

2828
"// This is completely generic, good for all derived classes\n",
2929
"// [[Rcpp::export]]\n",
30-
"SEXP set_value(SEXP Xptr, const std::string &name, SEXP Svalue) {\n",
30+
"SEXP set_value(SEXP Xptr, Rcpp::Nullable<Rcpp::String> &name, SEXP Svalue) {\n",
3131
" genericInterfaceBaseC *obj =\n",
3232
" get_genericInterfaceBaseC(Xptr);\n",
3333
" //std::cout << name << std::endl;\n",
34-
" obj->set_value( name, Svalue );\n",
34+
" if(name.isNull()) {\n",
35+
" obj->set_all_values( Svalue );\n",
36+
" } else {\n",
37+
" obj->set_value( Rcpp::as<std::string>(name), Svalue );\n",
38+
" }\n",
3539
" return(R_NilValue);\n",
3640
"}\n\n",
3741

nCompiler/inst/include/nCompiler/nC_inter/generic_class_interface.h

Lines changed: 9 additions & 213 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ class genericInterfaceBaseC {
7171
std::cout<<"Error: you should be in a derived genericInterfaceC class for get_value"<<std::endl;
7272
return R_NilValue;
7373
}
74+
virtual void set_all_values(SEXP Robj) {
75+
std::cout<<"Error: you should be in a derived genericInterfaceC class for set_all_values"<<std::endl;
76+
}
7477
virtual void set_value(const std::string &name, SEXP Svalue) {
7578
std::cout<<"Error: you should be in a derived genericInterfaceC class for set_value"<<std::endl;
7679
}
@@ -149,6 +152,9 @@ class interface_resolver : public Bases..., virtual public genericInterfaceBaseC
149152
SEXP get_value(const std::string &name) const override {
150153
return FirstFound::get_value(name);
151154
}
155+
void set_all_values(SEXP Robj) override {
156+
FirstFound::set_all_values(Robj);
157+
}
152158
void set_value(const std::string &name, SEXP Svalue) override {
153159
FirstFound::set_value(name, Svalue);
154160
}
@@ -173,6 +179,9 @@ class interface_resolver<> : virtual public genericInterfaceBaseC
173179
SEXP get_value(const std::string &name) const override {
174180
return FirstFound::get_value(name);
175181
}
182+
void set_all_values(SEXP Robj) override {
183+
FirstFound::set_all_values(Robj);
184+
}
176185
void set_value(const std::string &name, SEXP Svalue) override {
177186
FirstFound::set_value(name, Svalue);
178187
}
@@ -228,217 +237,4 @@ class method_base {
228237
template<class T>
229238
class genericInterfaceC;
230239

231-
// // Interface to class T.
232-
// template<class T>
233-
// class genericInterfaceC : public genericInterfaceBaseC {
234-
// public:
235-
// ~genericInterfaceC() {
236-
// #ifdef SHOW_DESTRUCTORS
237-
// std::cout<<"In derived genericInterfaceC destructor"<<std::endl;
238-
// #endif
239-
// }
240-
// // interface to a member of type P in class T
241-
// template<typename P>
242-
// class accessor_class : public accessor_base {
243-
// public:
244-
// typedef P T::*ptrtype;
245-
// ptrtype ptr;
246-
// accessor_class(ptrtype ptr) : ptr(ptr) {};
247-
248-
// SEXP get(const genericInterfaceBaseC *intBasePtr) const {
249-
// #ifdef SHOW_FIELDS
250-
// std::cout<<"in derived get"<<std::endl;
251-
// #endif
252-
// return Rcpp::wrap(reinterpret_cast<const T*>(intBasePtr)->*ptr);
253-
// }
254-
// void set(genericInterfaceBaseC *intBasePtr, SEXP Svalue) {
255-
// #ifdef SHOW_FIELDS
256-
// std::cout<<"in derived set"<<std::endl;
257-
// #endif
258-
// // reinterpret_cast<T*>(intBasePtr)->*ptr = Rcpp::as<P>(Svalue);
259-
// // Originally we defined an Rcpp::Exporter specialization as needed,
260-
// // which is called via as<>. However, we gain more flexibility in
261-
// // argument passing by defining new Rcpp::traits::input_parameter specializations.
262-
// // As a result, it is simpler her to create a new P object via this pathway.
263-
// reinterpret_cast<T*>(intBasePtr)->*ptr = P(typename Rcpp::traits::input_parameter<P>::type(Svalue));
264-
// }
265-
// };
266-
267-
// // static maps from character names
268-
// static int name_count;
269-
// typedef std::map<std::string,int> name2index_type;
270-
// static name2index_type name2index;
271-
272-
// typedef std::map<std::string, std::shared_ptr<accessor_base> > name2access_type;
273-
// typedef std::pair<std::string, std::shared_ptr<accessor_base> > name_access_pair;
274-
// static name2access_type name2access;
275-
276-
// // Enter a new (name, member ptr) pair to static maps.
277-
// template<typename P>
278-
// static name_access_pair field(std::string name, P T::*ptr) {
279-
// #ifdef SHOW_FIELDS
280-
// std::cout<<"adding "<<name<<std::endl;
281-
// #endif
282-
// name2index[name] = name_count++;
283-
// return name_access_pair(
284-
// name,
285-
// std::shared_ptr<accessor_base>(new accessor_class<P>(ptr))
286-
// );
287-
// }
288-
289-
// // hello world to see if static maps were populated.
290-
// void hw() {
291-
// std::cout<<"HW "<<name_count <<std::endl;
292-
// }
293-
294-
// // return a member as a SEXP, chosen by name.
295-
// // This is called via
296-
// // "SEXP get_value(SEXP Xptr, const std::string &name)"
297-
// // In turn this calls derived get in accessor_class above
298-
// SEXP get_value(const std::string &name) const {
299-
// #ifdef SHOW_FIELDS
300-
// std::cout<<"in derived get_value"<<std::endl;
301-
// #endif
302-
// name2access_type::const_iterator access = name2access.find(name);
303-
// if(access == name2access.end())
304-
// return R_NilValue;
305-
// return (access->second->get(this));
306-
// }
307-
308-
// void set_value(const std::string &name, SEXP Svalue ) {
309-
// #ifdef SHOW_FIELDS
310-
// std::cout<<"in derived set_value"<<std::endl;
311-
// #endif
312-
// name2access_type::iterator access = name2access.find(name);
313-
// if(access == name2access.end()) {
314-
// std::cout<<"Problem: \""<<name<<"\" is not a field in this nClass."<<std::endl;
315-
// return;
316-
// }
317-
// access->second->set(this, Svalue);
318-
// }
319-
320-
// /****** METHODS ******/
321-
// struct method_info {
322-
// // explicit saves the compiler from giving ambiguous
323-
// // constructor error from implicit copy and move constructors.
324-
// // I am not sure if this is the right way to resolve the issue.
325-
// method_info(const std::shared_ptr<method_base>& method_ptr_,
326-
// const args &args_) :
327-
// my_args(args_),
328-
// method_ptr(method_ptr_){};
329-
// args my_args;
330-
// std::shared_ptr<method_base> method_ptr;
331-
// };
332-
// // method_info needs a template argument, so this idea breaks.
333-
// typedef std::map<std::string, method_info > name2method_type;
334-
// typedef std::pair<std::string, method_info > name_method_pair;
335-
336-
337-
// SEXP call_method(const std::string &name, SEXP Sargs) {
338-
// #ifdef SHOW_METHODS
339-
// std::cout<<"in derived call_method"<<std::endl;
340-
// #endif
341-
// typename name2method_type::iterator method = name2method.find(name);
342-
// if(method == name2method.end()) {
343-
// std::cout<<"Problem: \""<<name<<"\" is not a method in this nClass."<<std::endl;
344-
// return R_NilValue;
345-
// }
346-
// if(TYPEOF(Sargs) != ENVSXP)
347-
// Rcpp::stop("nCompiler call_method should pass the calling environment.\n");
348-
// SEXP SinnerArgs = PROTECT(process_call_args(method->second.my_args.argVector, Sargs));
349-
// SEXP Sans = PROTECT(method->second.method_ptr->call(this, SinnerArgs));
350-
// UNPROTECT(2);
351-
// return Sans;
352-
// }
353-
354-
// template<typename P, typename ...ARGS>
355-
// class method_class : public method_base {
356-
// public:
357-
// typedef P (T::*ptrtype)(ARGS...);
358-
// ptrtype ptr;
359-
// method_class(ptrtype ptr) : ptr(ptr) {};
360-
361-
// SEXP call(genericInterfaceBaseC *intBasePtr, SEXP Sargs) {
362-
// #ifdef SHOW_METHODS
363-
// std::cout<<"in derived call"<<std::endl;
364-
// #endif
365-
// if(LENGTH(Sargs) != sizeof...(ARGS)) {
366-
// std::cout<<"Incorrect number of arguments"<<std::endl;
367-
// return R_NilValue;
368-
// }
369-
// return Rcpp::wrap(
370-
// expand_call_method_narg<P, T>::template call<ptrtype, ARGS...>(reinterpret_cast<T*>(intBasePtr), ptr, Sargs)
371-
// );
372-
// }
373-
// };
374-
375-
// /* Partial specialization on void return type avoids Rcpp::wrap<void>, which doesn't work. */
376-
// /* There might be a slightly more compact way to refactor just the Rcpp::wrap step, but */
377-
// /* this is a quick and simple solution:*/
378-
// template<typename ...ARGS>
379-
// class method_class<void, ARGS...> : public method_base {
380-
// public:
381-
// typedef void (T::*ptrtype)(ARGS...);
382-
// ptrtype ptr;
383-
// method_class(ptrtype ptr) : ptr(ptr) {};
384-
385-
// SEXP call(genericInterfaceBaseC *intBasePtr, SEXP Sargs) {
386-
// #ifdef SHOW_METHODS
387-
// std::cout<<"in derived call"<<std::endl;
388-
// #endif
389-
// if(LENGTH(Sargs) != sizeof...(ARGS)) {
390-
// std::cout<<"Incorrect number of arguments"<<std::endl;
391-
// return R_NilValue;
392-
// }
393-
// expand_call_method_narg<void, T>::template call<ptrtype, ARGS...>(reinterpret_cast<T*>(intBasePtr), ptr, Sargs);
394-
// return R_NilValue;
395-
// }
396-
// };
397-
398-
// // typedef std::map<std::string, std::shared_ptr<method_base> > name2method_type;
399-
// // typedef std::pair<std::string, std::shared_ptr<method_base> > name_method_pair;
400-
401-
// static name2method_type name2method;
402-
// template<typename P, typename ...ARGS>
403-
// static name_method_pair method(std::string name,
404-
// P (T::*fun)(ARGS... args),
405-
// const args& args_) {
406-
// #ifdef SHOW_METHODS
407-
// std::cout<<"adding method "<<name<<std::endl;
408-
// #endif
409-
// return
410-
// name_method_pair(name,
411-
// method_info(std::shared_ptr<method_base>(new method_class<P, ARGS...>(fun)), args_)
412-
// );
413-
// }
414-
// #ifdef NCOMPILER_USES_CEREAL
415-
// template<class Archive>
416-
// void _SERIALIZE_(Archive &archive) {
417-
// archive(cereal::base_class<genericInterfaceBaseC>(this));
418-
// }
419-
// #endif
420-
// };
421-
422-
423-
/* // From here down has been turned into macros above. */
424-
/* // This example uses the input name fooC */
425-
/* // followed by "field" and "method" entries. */
426-
/* template<> */
427-
/* int genericInterfaceC<fooC>::name_count = 0; */
428-
429-
/* template<> */
430-
/* genericInterfaceC<fooC>::name2index_type genericInterfaceC<fooC>::name2index {}; */
431-
432-
/* template<> */
433-
/* genericInterfaceC<fooC>::name2access_type genericInterfaceC<fooC>::name2access { */
434-
/* field("x", &fooC::x), */
435-
/* field("y", &fooC::y) */
436-
/* }; */
437-
438-
439-
/* template<> */
440-
/* genericInterfaceC<fooC>::name2method_type genericInterfaceC<fooC>::name2method { */
441-
/* method("print_val", &fooC::print_val) */
442-
/* }; */
443-
444240
#endif

0 commit comments

Comments
 (0)