cmdstan
                                
                                 cmdstan copied to clipboard
                                
                                    cmdstan copied to clipboard
                            
                            
                            
                        External c++ example fails
Summary:
Attempting to run the external c++ example fails with:
andrew@Andrews-MacBook-Air cmdstan-2.30.1 % make STANCFLAGS=--allow-undefined USER_HEADER=examples/bernoulli/make_odds.hpp examples/bernoulli/bernoulli # on Windows add .exe
--- Translating Stan model to C++ code ---
bin/stanc --allow-undefined --o=examples/bernoulli/bernoulli.hpp examples/bernoulli/bernoulli.stan
--- Compiling, linking C++ code ---
clang++ -std=c++1y -Wno-unknown-warning-option -Wno-tautological-compare -Wno-sign-compare -D_REENTRANT -Wno-ignored-attributes      -I stan/lib/stan_math/lib/tbb_2020.3/include    -O3 -I src -I stan/src -I lib/rapidjson_1.1.0/ -I lib/CLI11-1.9.1/ -I stan/lib/stan_math/ -I stan/lib/stan_math/lib/eigen_3.3.9 -I stan/lib/stan_math/lib/boost_1.78.0 -I stan/lib/stan_math/lib/sundials_6.1.1/include -I stan/lib/stan_math/lib/sundials_6.1.1/src/sundials    -DBOOST_DISABLE_ASSERTS          -c -include-pch stan/src/stan/model/model_header.hpp.gch -include examples/bernoulli/make_odds.hpp -x c++ -o examples/bernoulli/bernoulli.o examples/bernoulli/bernoulli.hpp
examples/bernoulli/bernoulli.hpp:24:62: error: template parameter redefines default argument
          stan::require_all_t<stan::is_stan_scalar<T0__>>* = nullptr>
                                                             ^
./examples/bernoulli/make_odds.hpp:6:62: note: previous default template argument defined here
          stan::require_all_t<stan::is_stan_scalar<T0__>>* = nullptr>
Not sure whether this is a stanc3 or cmdstan issue sorry!
Current Version:
v2.30.1
I can't reproduce this using gcc on Ubuntu 20.01, it's possible that this is compiler dependent. @rok-cesnovar - do you recall?
I think it may be a Mac issue - maybe clang? Will take a look over the weekend.
I seem to recall this being an issue with gcc being more permissive than clang in terms of multiple declarations.
There is a way around this (I believe) if you separate the compilation into multiple steps. If you add the manual template expansion
template double make_odds<double, nullptr>(const double&, std::ostream*);
to make_odds.hpp, you can then compile this to make_odds.o, then insert make_odds.o before bernoulli.o src/cmdstan/main.o in the final compile command. This should link properly, without the need to have two declarations in the same translation unit.
Full example:
- Add the above line to make_odds.hpp
- Run stanc --allow-undefined bernoulli.stan
- Compile bernoulli.hpp to bernoulli.o (this is the first step cmdstan does, see what command it uses)
- Compile make_odds.hpp to make_odds.o. This will probably use an almost identical command to the previous step, just with the files swapped out
- Compile the final executable, adding model.o to the list of sources. This is the second step cmdstan does.
On my machine, in full, the commands are (working from the top-level cmdstan directory with the model and header copied there):
bin/stanc --allow-undefined --o=bernoulli.hpp bernoulli.stan
g++ -std=c++1y -pthread -D_REENTRANT -Wno-sign-compare -Wno-ignored-attributes      -I stan/lib/stan_math/lib/tbb_2020.3/include    -O3 -I src -I stan/src -I stan/lib/rapidjson_1.1.0/ -I lib/CLI11-1.9.1/ -I stan/lib/stan_math/ -I stan/lib/stan_math/lib/eigen_3.3.9 -I stan/lib/stan_math/lib/boost_1.78.0 -I stan/lib/stan_math/lib/sundials_6.1.1/include -I stan/lib/stan_math/lib/sundials_6.1.1/src/sundials    -DBOOST_DISABLE_ASSERTS          -c -Wno-ignored-attributes   -x c++ -o bernoulli.o bernoulli.hpp
g++ -std=c++1y -pthread -D_REENTRANT -Wno-sign-compare -Wno-ignored-attributes      -I stan/lib/stan_math/lib/tbb_2020.3/include    -O3 -I src -I stan/src -I stan/lib/rapidjson_1.1.0/ -I lib/CLI11-1.9.1/ -I stan/lib/stan_math/ -I stan/lib/stan_math/lib/eigen_3.3.9 -I stan/lib/stan_math/lib/boost_1.78.0 -I stan/lib/stan_math/lib/sundials_6.1.1/include -I stan/lib/stan_math/lib/sundials_6.1.1/src/sundials    -DBOOST_DISABLE_ASSERTS          -c -Wno-ignored-attributes   -x c++ -o make_odds.o make_odds.hpp
g++ -std=c++1y -pthread -D_REENTRANT -Wno-sign-compare -Wno-ignored-attributes      -I stan/lib/stan_math/lib/tbb_2020.3/include    -O3 -I src -I stan/src -I stan/lib/rapidjson_1.1.0/ -I lib/CLI11-1.9.1/ -I stan/lib/stan_math/ -I stan/lib/stan_math/lib/eigen_3.3.9 -I stan/lib/stan_math/lib/boost_1.78.0 -I stan/lib/stan_math/lib/sundials_6.1.1/include -I stan/lib/stan_math/lib/sundials_6.1.1/src/sundials    -DBOOST_DISABLE_ASSERTS                -Wl,-L,"/home/brian/Dev/cpp/cmdstan/stan/lib/stan_math/lib/tbb" -Wl,-rpath,"/home/brian/Dev/cpp/cmdstan/stan/lib/stan_math/lib/tbb"    make_odds.o  bernoulli.o src/cmdstan/main.o        -Wl,-L,"/home/brian/Dev/cpp/cmdstan/stan/lib/stan_math/lib/tbb" -Wl,-rpath,"/home/brian/Dev/cpp/cmdstan/stan/lib/stan_math/lib/tbb"   stan/lib/stan_math/lib/sundials_6.1.1/lib/libsundials_nvecserial.a stan/lib/stan_math/lib/sundials_6.1.1/lib/libsundials_cvodes.a stan/lib/stan_math/lib/sundials_6.1.1/lib/libsundials_idas.a stan/lib/stan_math/lib/sundials_6.1.1/lib/libsundials_kinsol.a  stan/lib/stan_math/lib/tbb/libtbb.so.2 -o bernoulli
Edit: As an added bonus, since you're manually expanding the template here you don't really need to do the SNIFAE-style require magic. The following header will also compile just file:
#include <stan/model/model_header.hpp>
#include <ostream>
namespace bernoulli_model_namespace {
template <typename T0__, void* = nullptr>
stan::promote_args_t<T0__> make_odds(const T0__& theta,
                                     std::ostream* pstream__) {
  return theta / (1 - theta);
}
template double make_odds<double>(const double&, std::ostream*);
}  // namespace bernoulli_model_namespace
@andrjohns if you have a local copy which has develop cmdstan / master stanc, would you mind trying the updated examples from https://github.com/stan-dev/docs/pull/626?
@andrjohns if you have a local copy which has develop cmdstan / master stanc, would you mind trying the updated examples from https://github.com/stan-dev/docs/pull/626?
Brilliant! Both the templated make_odds and the my_dot_self derivative overloads are compiling without issue
Great!