diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9278fff2f93968e5a66bc3d4099b37c64c4b9fd2..463f282dd18680402fd211b7365fbc339d7d5c26 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -84,7 +84,9 @@ target_link_libraries(teqpcpp PUBLIC teqpinterface PUBLIC autodiff)
 
 if (TEQP_TESTTEQPCPP)
   add_executable(test_teqpcpp "${CMAKE_CURRENT_SOURCE_DIR}/interface/CPP/test_teqpcpp.cpp")
-  target_link_libraries(test_teqpcpp PUBLIC teqpcpp PRIVATE Catch2WithMain)
+  target_link_libraries(test_teqpcpp PUBLIC teqpcpp)
+  add_executable(bench_teqpcpp "${CMAKE_CURRENT_SOURCE_DIR}/interface/CPP/bench_teqpcpp.cpp")
+  target_link_libraries(bench_teqpcpp PUBLIC teqpcpp PRIVATE Catch2WithMain)
 endif()
 
 if (TEQP_JAVASCRIPT_MODULE)
diff --git a/interface/CPP/bench_teqpcpp.cpp b/interface/CPP/bench_teqpcpp.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3acb69efb1398556a4fd6c1814599124f437b566
--- /dev/null
+++ b/interface/CPP/bench_teqpcpp.cpp
@@ -0,0 +1,46 @@
+#include <catch2/catch_test_macros.hpp>
+#include <catch2/benchmark/catch_benchmark_all.hpp>
+
+#include "teqpcpp.hpp"
+
+using namespace teqp::cppinterface;
+
+#include "teqp/derivs.hpp"
+
+using namespace teqp;
+
+TEST_CASE("Test C++ interface", "[C++]")
+{
+    auto modelnovar = teqp::build_multifluid_model({ "Methane","Ethane" }, "../mycp");
+    teqp::AllowedModels model = modelnovar;
+    auto z = (Eigen::ArrayXd(2) << 0.5, 0.5).finished();
+    SECTION("Ar01") {
+        double Ar01 = get_Arxy(model, 0, 1, 300, 3, z);
+    }
+    SECTION("critical trace") {
+        double Tc1 = modelnovar.redfunc.Tc(0);
+        auto rhovec0 = (Eigen::ArrayXd(2) << 1/modelnovar.redfunc.vc(0), 0).finished();
+        auto cr = trace_critical_arclength_binary(model, Tc1, rhovec0);
+        std::cout << cr.dump(1) << std::endl;
+    }
+}
+
+TEST_CASE("Benchmark C++ interface", "[C++]")
+{
+    teqp::AllowedModels model = teqp::build_multifluid_model({ "Methane", "Ethane"}, "../mycp");
+    auto z = (Eigen::ArrayXd(2) << 0.5, 0.5).finished();
+    
+    auto model1novar = teqp::build_multifluid_model({ "Methane" }, "../mycp");
+    teqp::AllowedModels model1 = model1novar;
+    auto z1 = (Eigen::ArrayXd(1) << 1).finished();
+    
+    BENCHMARK("Ar01 two components") {
+        return get_Arxy(model, 0, 1, 300, 3, z);
+    }; 
+    BENCHMARK("Ar01 one component w/ Arxy (runtime lookup)") {
+        return get_Arxy(model1, 0, 1, 300, 3, z1);
+    }; 
+    BENCHMARK("Ar01 one component w/ Ar01 directly") {
+        return TDXDerivatives<decltype(model1novar)>::get_Arxy<0,1,ADBackends::autodiff>(model1novar, 300, 3, z1);
+    }; 
+}
diff --git a/interface/CPP/teqpcpp.cpp b/interface/CPP/teqpcpp.cpp
index 331bcd6872fa28e7da489e4a72084a2d3d1804f0..4706160cf9d9eb31aba3d5e05bacb1baa4a31241 100644
--- a/interface/CPP/teqpcpp.cpp
+++ b/interface/CPP/teqpcpp.cpp
@@ -1,20 +1,17 @@
-// Pulls in the AllowedModels variant
 #include "teqp/models/fwd.hpp"
 
 #include "teqpcpp.hpp"
 #include "teqp/derivs.hpp"
 #include "teqp/algorithms/critical_tracing.hpp"
 
-double teqp::cppinterface::get_Arxy(const void* modelptr, const int NT, const int ND, const double T, const double rho, const Eigen::ArrayXd &molefracs){
-    const teqp::AllowedModels& model = *static_cast<const teqp::AllowedModels*>(modelptr);
+double teqp::cppinterface::get_Arxy(const teqp::AllowedModels& model, const int NT, const int ND, const double T, const double rho, const Eigen::ArrayXd &molefracs){
     return std::visit([&](const auto& model) {
         using tdx = teqp::TDXDerivatives<decltype(model), double, std::decay_t<decltype(molefracs)>>;
         return tdx::template get_Ar(NT, ND, model, T, rho, molefracs);
     }, model);
 }
 
-nlohmann::json teqp::cppinterface::trace_critical_arclength_binary(const void* modelptr, const double T0, const Eigen::ArrayXd &rhovec0) {
-    const teqp::AllowedModels& model = *static_cast<const teqp::AllowedModels*>(modelptr);
+nlohmann::json teqp::cppinterface::trace_critical_arclength_binary(const teqp::AllowedModels& model, const double T0, const Eigen::ArrayXd &rhovec0) {
     return std::visit([&](const auto& model) {
         using crit = teqp::CriticalTracing<decltype(model), double, std::decay_t<decltype(rhovec0)>>;
         return crit::trace_critical_arclength_binary(model, T0, rhovec0, "");
diff --git a/interface/CPP/teqpcpp.hpp b/interface/CPP/teqpcpp.hpp
index 628c847181e61eca874034cd3f59ba77fd540886..2b0de35b1087d6fb717e43db0478f7a297deff69 100644
--- a/interface/CPP/teqpcpp.hpp
+++ b/interface/CPP/teqpcpp.hpp
@@ -3,11 +3,14 @@
 #include <Eigen/Dense>
 #include "nlohmann/json.hpp"
 
+// Pulls in the AllowedModels variant
+#include "teqp/models/fwd.hpp"
+
 namespace teqp {
     namespace cppinterface {
 
         // Wrapper functions
-        double get_Arxy(const void* model, const int NT, const int ND, const double T, const double rho, const Eigen::ArrayXd& molefracs);
-        nlohmann::json trace_critical_arclength_binary(const void* model, const double T0, const Eigen::ArrayXd& rhovec0);
+        double get_Arxy(const teqp::AllowedModels& model, const int NT, const int ND, const double T, const double rho, const Eigen::ArrayXd& molefracs);
+        nlohmann::json trace_critical_arclength_binary(const teqp::AllowedModels& model, const double T0, const Eigen::ArrayXd& rhovec0);
     }
 }
\ No newline at end of file
diff --git a/interface/CPP/test_teqpcpp.cpp b/interface/CPP/test_teqpcpp.cpp
index 2644aca16ab4f8641c78a505db0a869adfecddd4..326ed775774069ba7f41a7d57e303298de96f9c0 100644
--- a/interface/CPP/test_teqpcpp.cpp
+++ b/interface/CPP/test_teqpcpp.cpp
@@ -1,49 +1,18 @@
-#include <catch2/catch_test_macros.hpp>
-#include <catch2/benchmark/catch_benchmark_all.hpp>
+/**
+* This is a minimal example of the use of the C++ interface around teqp
+* 
+* The point of the interface is to reduce compilation time, as compilation 
+* of this file should be MUCH faster than compilation with the full set of 
+* algorithms and models because the template instantiations are all included in the 
+* library that this file is linked against and the compiler does not need to resolve
+* all the templates every time this file is compiled
+*/
 
-#include "teqpcpp.hpp"
-
-using namespace teqp::cppinterface;
-
-// Pulls in the AllowedModels variant
-#include "teqp/models/fwd.hpp"
-
-#include "teqp/derivs.hpp"
 
-using namespace teqp;
-
-TEST_CASE("Test C++ interface", "[C++]")
-{
-    auto modelnovar = teqp::build_multifluid_model({ "Methane","Ethane" }, "../mycp");
-    teqp::AllowedModels model = modelnovar;
-    auto z = (Eigen::ArrayXd(2) << 0.5, 0.5).finished();
-    SECTION("Ar01") {
-        double Ar01 = get_Arxy(&model, 0, 1, 300, 3, z);
-    }
-    SECTION("critical trace") {
-        double Tc1 = modelnovar.redfunc.Tc(0);
-        auto rhovec0 = (Eigen::ArrayXd(2) << 1/modelnovar.redfunc.vc(0), 0).finished();
-        auto cr = trace_critical_arclength_binary(&model, Tc1, z);
-        std::cout << cr.dump(1) << std::endl;
-    }
-}
+#include "teqpcpp.hpp"
 
-TEST_CASE("Benchmark C++ interface", "[C++]")
-{
-    teqp::AllowedModels model = teqp::build_multifluid_model({ "Methane", "Ethane"}, "../mycp");
+int main() {
+    teqp::AllowedModels model = teqp::build_multifluid_model({ "Methane", "Ethane" }, "../mycp");
     auto z = (Eigen::ArrayXd(2) << 0.5, 0.5).finished();
-    
-    auto model1novar = teqp::build_multifluid_model({ "Methane" }, "../mycp");
-    teqp::AllowedModels model1 = model1novar;
-    auto z1 = (Eigen::ArrayXd(1) << 1).finished(); 
-    
-    BENCHMARK("Ar01 two components") {
-        return get_Arxy(&model, 0, 1, 300, 3, z);
-    }; 
-    BENCHMARK("Ar01 one component w/ Arxy (runtime lookup)") {
-        return get_Arxy(&model1, 0, 1, 300, 3, z1);
-    }; 
-    BENCHMARK("Ar01 one component w/ Ar01 directly") {
-        return TDXDerivatives<decltype(model1novar)>::get_Arxy<0,1,ADBackends::autodiff>(model1novar, 300, 3, z1);
-    }; 
-}
+    double Ar01 = teqp::cppinterface::get_Arxy(model, 0, 1, 300, 3, z);
+}
\ No newline at end of file