mardi 21 mai 2019

Conditionally enable non-template function c++

Background

I'm working on a C++ project in High Performance Computing using MPI. I have a function with a few different overloads, that I use to convert different types into strings:

void append(std::string& s, int value);
void append(std::string& s, void* value);
void append(std::string& s, MPI_Request request); 

This worked fine while I was using Open MPI. In OpenMPI, MPI_Request is an alias for ompi_request_t*, so each overload has a different signature.

Recently, however, I tried compiling the code with MPICH. In MPICH, MPI_Request is an alias for int, and the result is that the above code fails to compile because append is defined for int twice:

/home/me/NimbleSM/src/mpi-buckets/src/mpi_err.hpp: At global scope:
/home/me/NimbleSM/src/mpi-buckets/src/mpi_err.hpp:28:6: error: redefinition of ‘void append(std::__cxx11::string&, int)’
 void append(std::string& s, int i) { s.append(std::to_string(i)); }
      ^~~
/home/me/NimbleSM/src/mpi-buckets/src/mpi_err.hpp:17:6: note: ‘void append(std::__cxx11::string&, MPI_Request)’ previously defined here
 void append(std::string& s, MPI_Request request)

Question

How should I write append(std::string&, MPI_Request) so that the compiler ignores it when MPI_Request is defined as an int, but recognizes it when MPI_Request is a library type?

Attempted solution: enable_if fails

I attempted to write a solution based on std::enable_if, where the function is only enabled if MPI_Request is a different type than int.

auto append(std::string& s, MPI_Request request)
    -> typename std::enable_if<!std::is_same<MPI_Request, int>::value, void>::type
{ 
    str(s, (void*)request); 
}

This fails because when MPI_Request is the same as int, the statement is always false, and since it's not dependent on any template parameters, the compiler flat-out refuses to compile it.

How do I fix this, and make append contingent on MPI_Request being different from int?

Aucun commentaire:

Enregistrer un commentaire