Skip to content

Rcpp-extending: implementing Rcpp:wrap() for a templated type #165

Description

@cauthmann

quoting from Rcpp-extending:

It is perfectly valid to declare a partial specialization for the Rcpp::wrap template. The compiler will identify the appropriate overload:

namespace Rcpp {
  namespace traits {
    template < typename T > SEXP wrap ( const Bling <T>& ) ;
  }
}

However

  • there is no wrap template in the Rcpp::traits namespace, only in Rcpp
  • partial specialization of template functions is not possible. The code shows a separate template with additional overloaded function signatures. The difference is that specialization replaces the original template, while overloading doesn't. Both the original template and the custom template can offer a function signature that matches Bling.
  • It doesn't work. I'm not sure about the exact resolution mechanics (even gotw #49 isn't too clear, and also claims poor compiler support), but both gcc and clang pick the "wrong" one, i.e. the default template which doesn't know Bling, thus fails.

Here's the code I used to verify the problem. Note that it fails no matter if the template goes into Rcpp or Rcpp::traits

class Foo {
    public:
        Foo(int t) : t(t) {}
        ~Foo() {}
        int t;
};

template<typename T>
class Bar {
    public:
        Bar(T t) : t(t) {}
        ~Bar() {}
        T t;
};

#include <RcppCommon.h>
namespace Rcpp {
    template<> SEXP wrap(const Foo &f);

    template<typename T> SEXP wrap(const Bar<T> &b);
}

#include <Rcpp.h>
#include <RInside.h>

template<> SEXP Rcpp::wrap(const Foo &f) {
    return Rcpp::wrap(f.t);
}

template<typename T> SEXP Rcpp::wrap(const Bar<T> &b) {
    return Rcpp::wrap(b.t);
}


int main(int argc, char *argv[]) {
    // sorry for using RInside; it's what I know.
    RInside R(argc, argv);

    // try to wrap 'em
    Foo f(42);
    R["foo"] = f; // works

    Bar<int> b(42);
    R["bar"] = b; // does not compile:
    // error: static assertion failed: cannot convert type to SEXP

}

Fun fact: if you remove the declaration and only keep the implementation after including Rcpp.h, it compiles in gcc. I have absolutely no idea why it does. Or why it does in gcc, but not in clang.

Am I doing something wrong? Does this work, or did this work, for anyone else? Or are we actually facing the same issue as with Rcpp::as, where we need to fall back to a template class, where partial specialization works as required?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions