Home > Enterprise >  Compile same source with diffrent aliases
Compile same source with diffrent aliases

Time:06-08

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 #ifdefs.

  • Related