Metaprogramming, routing 'rev' to 'prim'


#1

Hi -

I have a question regarding metaprogramming.
How to re-create the problem:

If you run git clone -b feature/issue-758-add-dot-product-coviariance-function on my fork, you can clone the branch and run as is… I changed the compiler to g++ in make/default_compiler_options i.e. CC = g++

running ./runTests.py test/unit/math/prim/mat/fun/gp_dot_prod_cov_test.cpp will work fine, as prim is implemented fine.

running ./runTests.py test/unit/math/prim/mat/fun/gp_dot_prod_cov_test.cpp will work fine initially, but there are only two dummy tests that make sure the proper function is being called. if you uncomment line 46 you will see the “routing” issue in the form of a compiler error.

This function call is calling the wrong implementation in ‘prim’
The rev functions need to have two separate versions (following the datatypes @syclik added for gp_cov_exp_quad.hpp):
( c++ -> stan )

  1. calls prim with dot_product.hpp (for std::vector<Eigen::Matrix<stan::math::var, -1, 1> > -> row_vector[N])
  2. calls prim without dot_product.hpp (for std::vector<stan::math::var> -> real x[N])

Currently, both rev versions are both calling the prim version that uses dot_product.hpp (template <typename T_x, typename T_sigma>). This is probably because one of the gp_dot_prod_cov.hpp is not templated.
So the question is this how do I use metaprogamming, either a template, or enable_if, to make sure that rev is calling the correct prim? I have tried various enable_if statements and different templates.

As one attempt to remedy the problem, I tried the templating strategy in dot_product.cpp. Why do dot_product.cpp tests not compile with the template <int R1, ...> etc arguments?


#2

Sorry this didn’t get answered sooner. You can use disable_if to turn off an instantiation if you can write a template expression to catch the types you want to turn off.

But you want to figure out why it’s not instantiating the one you think it should. In general, C++ considers all the base template definitions with matching names (ones that aren’t template specializations), and chooses the most specific one to match the call. Then it takes the most specific specialization available for that base template. If either of these steps results in ambiguity, compilation fails. So the only way you get the wrong version is if the right one hasn’t been included or if the wrong one’s more specific.