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