Skip to content

Commit 2ed7e49

Browse files
rstubeddelbuettel
authored andcommitted
Add example for .factory (#938)
* Add example for .factory * Replace c++ by cpp
1 parent f0bae39 commit 2ed7e49

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed

vignettes/Rcpp-modules.Rmd

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,72 @@ It can be used to perform operations, releasing resources, etc ...
855855
The finalizer is called automatically when the \proglang{R} object that encapsulates
856856
the \proglang{C++} object is garbage collected.
857857
858+
### Object factories
859+
860+
The `.factory` member function of `class_` can be used to register a
861+
[factory](https://en.wikipedia.org/wiki/Factory_method_pattern) that
862+
can be used as alternative to a constructor. A factory can be a
863+
static member function or a free function that returns a pointer to
864+
the target class. Typical use-cases include creating objects in a
865+
hierarchy:
866+
867+
```cpp
868+
#include <Rcpp.h>
869+
using namespace Rcpp;
870+
871+
// abstract class
872+
class Base {
873+
public:
874+
virtual ~Base() {}
875+
virtual std::string name() const = 0;
876+
};
877+
878+
// first derived class
879+
class Derived1: public Base {
880+
public:
881+
Derived1() : Base() {}
882+
virtual std::string name() const {
883+
return "Derived1";
884+
}
885+
};
886+
887+
// second derived class
888+
class Derived2: public Base {
889+
public:
890+
Derived2() : Base() {}
891+
virtual std::string name() const {
892+
return "Derived2";
893+
}
894+
};
895+
896+
Base *newBase( const std::string &name ) {
897+
if (name == "d1"){
898+
return new Derived1;
899+
} else if (name == "d2"){
900+
return new Derived2;
901+
} else {
902+
return 0;
903+
}
904+
}
905+
906+
RCPP_MODULE(mod) {
907+
Rcpp::class_< Base >("Base")
908+
.factory<const std::string&>(newBase)
909+
.method("name", &Base::name);
910+
}
911+
```
912+
913+
The `newBase` method returns a pointer to a `Base` object. Since that
914+
class is an abstract class, the objects are actually instances of
915+
`Derived1` or `Derived2`. The same behavior is now available in R:
916+
917+
```{r, eval=FALSE}
918+
dv1 <- new(Base, "d1")
919+
dv1$name() # returns "Derived1"
920+
dv2 <- new(Base, "d2")
921+
dv2$name() # returns "Derived2"
922+
```
923+
858924
### S4 dispatch
859925

860926
When a \proglang{C++} class is exposed by the `class_` template,

0 commit comments

Comments
 (0)