jeudi 23 septembre 2021

C++ Type, Function, and value aliasing for potentially undefined types

Suppose I have two libraries, let's arbitrarily call them "CUDA" and "HIP". These two libraries just so happen to have eerily similar interfaces, and I want to wrap these interfaces into a templated class where the template parameter defines which library is called. So far I have

#define ALIAS_FUNCTION(Alias_,Original_)              \
  template <typename... Args> Alias_(Args&&... args)  \
  -> decltype(Original_(std::forward<Args>(args)...)) \
  { return Original_(std::forward<Args>(args)...);}

enum class Selector {CUDA,HIP};

template <Selector T> struct Interface;

#if (havecuda)
template <>
struct Interface<Selector::CUDA>
{
  using error_type = cudaError_t;
  static const auto success = cudaSuccess;

  ALIAS_FUNCTION(static constexpr getLastError,cudaGetLastError);
};
#endif

#if (havehip)
template <>
struct Interface<Selector::HIP>
{
  using error_type = hipError_t;
  static const auto success = hipSuccess;

  ALIAS_FUNCTION(static constexpr getLastError,hipGetLastError);
};
#endif

While this works it is extremely painful to maintain, as I need to duplicate every alias, as well as make sure a fair chunk of boilerplate is correct. Not to mention the macros. What I want ideally is keep it all in one definition so something like:

template <Selector T>
struct Interface
{
  using error_type = std::conditional<T==Selector::CUDA,cudaError_t,hipError_t>;
  // do something similar to solve the function and variable aliasing
};

but alas std::conditional requires both types to be at least declared. Is there a cleverer solution here? It should ideally also be C++11.

Aucun commentaire:

Enregistrer un commentaire