Instantiating a Variadic template within a class

Hey all - I’m trying to instantiate a variadic template within class, I’m wondering if anyone’s done this before. Cpp docs say something like this:

template<class...T> void func(T...a){}; Cool, we have a templated function, that returns void, and takes in an arbitrary amount of type T’s called a.

So here’s a dummy class, where f is a function I want to take in one specific data type, and an arbitrary amount afterward.

template <typename F>
class dummy {
  const F& f;  // declaration
  dummy(const F &f) :  // function signature
  f(f)  // assignment
{
  // do something
}
}

I’ve tried things like: using f(Args...ags) where Args is a template specified at the top, in the delcaration block, in the assignment block, or in dummy's function signature, with no luck.

Wondering if anyone’s done this before?

What’s your signature for f?

In c++, the signature looks like this:

Eigen::Matrix<scalar, -1, -1> 
  f(Eigen::Matrix<T_x, -1, -1>& x, Scalar... scalar);

I think my syntax is correct.

One special case of this would be:

Eigen::Matrix<typename stan::math::return_type<T_x, T_s, T_l>::type, -1, -1> 
  gp_exp_quad_cov(Eigen::Matrix<T_x, -1, -1>& x, T_s sigma, T_l length_scale);

The link below came up, and this looks like it will help, as it has the same variadic template setup I need (first is a unique type (i.e. Eigen::Matrix), rest are same type (i.e. stan::math::var or scalar)) with just the caveat that I need f to be a member of of the class, so that it can be read it from outside:

edit:

hold on I have an idea…

yeah I haven’t implemented this, but you never need to specify the input args for f you can just create the parameter pack in the class. I think I have it, thanks.

oh it’s really easy… not sure what I was doing:

const F & f_(Eigen::Matrix<T_X, Eigen::Dynamic, Eigen::Dynamic>, T_scalar...);

in declarations

1 Like

So here. I have a class, and I’ve properly instantiated with a functor in the declarations block.

Now, when I’m trying to call the function within the class, I’m running into issues.

Say I call dummy with:

Eigen::Matrix<Scalar_t, -1, -1> x;
// fill x with stuff here

stan::math::dummy<functor_f>dummy(f(), x)
template <typename F>
class dummy {
  const F& f(Eigen::Matrix<Scalar_t, -1, -1>, T_theta...); 
  const Eigen::Matrix<Scalar_t, -1, -1> X;
  dummy(const F &f, Eigen::Matrix<T_scalar, -1, -1> X)
{
  // do something
}
}

What am I missing?

Can you make a minimum reproducible example so I can see what the error is?

Yes, thanks Steve.

Here’s my test functor. It just takes an Eigen::Matrix then creates an std::vector<Eigen::Matrix<scalar, -1, 1>> view and pipes it into a covariance function. It’s untested, but this isn’t the issue.

struct cov_exp_quad_functor {
    template <typename T0__, typename T1__, typename T2__>
        Eigen::Matrix<typename boost::math::tools::promote_args<T0__, T1__, T2__>::type,
                      Eigen::Dynamic,Eigen::Dynamic>
    operator()(const Eigen::Matrix<T0__, -1, -1>& x,
               const T1__& sigma,
               const T2__& length_scale) const {
      typedef typename boost::math::tools::promote_args<T0__, T1__>::type scalar;
      std::vector<Eigen::Matrix<T0__, -1, 1>> x_in(x.cols());
      for (size_t i = 0; i < x.cols(); ++i) {
        x_in.resize(x.rows(), 1);
        x_in[i] = x.col(i);
      }
      Eigen::Matrix<scalar, -1, -1> cov =
        stan::math::gp_exp_quad_cov(x_in, sigma, length_scale);
      return cov;
    }
};

Then, the class I’m building:

template <bool propto, typename F, typename T_y, typename T_X, typename T_theta>
class gp_lpdf {
public:
  const F& f_(const Eigen::Matrix<T_X, Eigen::Dynamic, Eigen::Dynamic>, T_theta...);
  const Eigen::Matrix<T_X, Eigen::Dynamic, Eigen::Dynamic>& X_;
  gp_lpdf(const F& f_(const Eigen::Matrix<T_X, Eigen::Dynamic, Eigen::Dynamic>, T_theta...),
          const Eigen::Matrix<T_X, Eigen::Dynamic, Eigen::Dynamic>& X_)
  {
    // do some things
  };
};

And this is one of the ways I’ve tried to instantiate the class:

  Eigen::Matrix<double, -1, -1> x; x.resize(3, 3);
  x << 1, 2, 3, 4, 5, 6, 7, 8, 9;
  
  stan::math::gp_lpdf <false, cov_exp_quad_functor,
                       double, double, stan::math::var>
    gp_lpdf(cov_exp_quad_functor(), x);

It works fine with no x data matrix.

This is all on my stan/math fork, under feature/issue-1011-gp-cov-fun

Apologies for the delay I just got settled in Helsinki. I’ll throw this up on godbolt tmrw and see what’s going on.

Also for your other message I never got around to ordering those shirts! May ask him to make them for Stancon this year

don’t worry about it, I can do this. Didn’t know about Godbolt

I don’t need you to debug it for me, I was just wondering if there was something dumb I’m doing you would be able to call out off hand

@stevebronder did you get Godbolt working for something that’s heavily dependent on the math library?

I’m looking into cce right now but don’t have the motivation to figure out how to integrate it with Stan math right now.

Just wondering if there’s a faster way.