TLDR: Can you compile the same source code with different headers defining diffrent aliases?
I have created a library, with a set of functions coded using a couple of aliased type in the header.
algorithm_2d.h
using Point = Eigen::Vector2d;
using Vector = Eigen::Vector2d;
algorithm.cpp
Vector& scale_vector(
Vector &v,
double s)
{
double len = v.norm();
if (len != 0.0) { v *= s/len;}
return v;
}
double distance_between_points(
Point const &p1,
Point const &p2)
{
return (p2 - p1).norm();
}
Now I would like to compile the same algorithm.cpp
but with different aliases:
algorithm_3d.h
using Point = Eigen::Vector3d;
using Vector = Eigen::Vector3d;
I am building using CMake
with pybind11
as this is mainly a python library.
I would prefer not having to use templates, as that would cause me to have to define every single type in every function. And as you can see in the snippet, it would make it a lot less readable, and this is already a mathematically complicated algorithm (rest of the code not shown).
EDIT:
Another example to make it clear what I mean by using the aliases. If I were using templates, each time this function is called
.h
using PointSet = std::vector<Point, Eigen::aligned_allocator<Point> >;
.cpp
Vector compute_left_tangent(
PointSet const &pts,
int end,
{
Vector tHat1 = PointSet[end 1] - PointSet[end];
tHat1 = tHat / distance_between_points(PoinSet[end],PointSet[end 1])
}
I don't want to have to add the <Eigen::Vector2d,..., etc>
every time I call one of these functions. Maybe there is a way of doing this with templates that I am missing?
CodePudding user response:
Given the following template file: (call it algorithm.cpp.tmpl
)
using Point = @_flavor@;
using Vector = @_flavor@;
#include "algorithm.cpp"
You can have CMake generate flavors automatically and build them as part of some_target
:
set(FLAVORS Eigen::Vector2d Eigen::Vector3d)
foreach(_flavor ${FLAVORS})
string(MAKE_C_IDENTIFIER ${_flavor} _flavor_slug)
set(_flavor_out algorithm_${_flavor_slug}.cpp)
configure_file(algorithm.cpp.tmpl ${_flavor_out} @ONLY)
target_sources(some_target PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/${_flavor_out})
endforeach()
CodePudding user response:
Sure, this is one use of compiler defines are for.
algorithm.h
#ifdef 2D
using Point = Eigen::Vector2d; using Vector = Eigen::Vector2d;
#endif
#ifdef 3D
using Point = Eigen::Vector3d; using Vector = Eigen::Vector3d;
#endif
algorithm.cpp
Vector& scale_vector(
Vector &v,
double s) {
double len = v.norm();
if (len != 0.0) { v *= s/len;}
return v; }
double distance_between_points(
Point const &p1,
Point const &p2) {
return (p2 - p1).norm(); }
See also https://en.cppreference.com/w/cpp/preprocessor/conditional
Now you just need to tell your compiler to define 2D or 3D.
g -D3D ...
I think the microsoft compiler uses somtehing like
/D3D
CodePudding user response:
Template is your friend here:
template<typename T>
T& scale_vector(
T& v,
double s)
{
double len = v.norm();
if (len != 0.0) { v *= s/len;}
return v;
}
template<typename T>
double distance_between_points(
const T&p1,
const T&p2)
{
return (p2 - p1).norm();
}
https://godbolt.org/z/fY7hb8df7
No code generators, no macros, no #ifdef
s.