【发布时间】:2019-05-21 21:08:32
【问题描述】:
背景
我正在使用 MPI 进行高性能计算的 C++ 项目。我有一个带有几个不同重载的函数,用于将不同的类型转换为字符串:
void append(std::string& s, int value);
void append(std::string& s, void* value);
void append(std::string& s, MPI_Request request);
这在我使用 Open MPI 时运行良好。在 OpenMPI 中,MPI_Request 是 ompi_request_t* 的别名,因此每个重载都有不同的签名。
不过,最近我尝试使用 MPICH 编译代码。在MPICH中,MPI_Request是int的别名,结果是上面的代码编译失败,因为append为int定义了两次:
/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)
问题
我应该如何编写append(std::string&, MPI_Request),以便编译器在MPI_Request 被定义为int 时忽略它,但在MPI_Request 是库类型时识别它?
尝试的解决方案:enable_if 失败
我尝试编写基于std::enable_if 的解决方案,其中仅当MPI_Request 与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);
}
这会失败,因为当MPI_Request 与int 相同时,该语句始终为假,并且由于它不依赖于任何模板参数,因此编译器完全拒绝编译它。
我该如何解决这个问题,并使append 取决于MPI_Request 与int 不同?
【问题讨论】:
-
如果
MPI_Request是int,您是否想要与int重载相同的行为? -
没有办法用非模板模拟 SFINAE。 SFINAE 的主要使用点是避免使用不能在函数体中使用的类型来实例化函数。非模板不允许你这样做。
-
如果 MPI_Request 是 int,我希望编译器忽略该函数。所以它只是假装 MPI_Request 重载不存在
-
也许有一个设计问题需要在更高的层次上解决,因为无论你做什么,你都永远无法区分
void append(std::string& s, int value)和void append(std::string& s,int mpi_request)(相同的签名) -
我不需要区分它们;如果 MPI_Request 不是 int,我只需要有一个重载。如果它是一个 int,我可以调用
int版本(我只需要非 int 版本不存在)
标签: c++ c++11 mpi portability