我正在使用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
相同时,该语句始终为false,并且由于它不依赖于任何模板参数,因此编译器完全拒绝编译它。
如何解决此问题,并使append
取决于MPI_Request
与int
不同?
答案 0 :(得分:2)
那是不幸的。底线是enable_if
仅可在需要T模板的SFINAE上下文中使用。要根据您的想法进行迭代,我们可以在返回类型中指定我们的要求,以便模板仅与MPI_Request
匹配,并且仅在MPI_Request
类型不是int
的情况下匹配。
#include <string>
#include <type_traits>
using MPI_Request = int;// Or something else
template<typename T>
using T_is_MPI_and_not_also_int = std::conjunction<std::is_same<T,MPI_Request>, std::negation<std::is_same<MPI_Request,int>>>;
template<typename T>
std::enable_if_t<T_is_MPI_and_not_also_int<T>::value,void>
append(std::string& s, T request);
Full example,您甚至可以看到哪一行cout
内联到main。
答案 1 :(得分:2)
您可以将其设为具有默认模板参数的功能模板,从而使SFINAE能够正常工作:
void append(std::string& s, int value);
void append(std::string& s, void* value);
template <typename MPI_Request_ = MPI_Request,
typename std::enable_if<
!std::is_same<MPI_Request_, int>::value
&& std::is_same<MPI_Request_, MPI_Request>::value
, int>::type = 0>
void append(std::string& s, MPI_Request_ request)
{
str(s, (void*)request);
// Or, if you want the implementation in the source file,
// call another function like: append_mpi_request(s, request);
}
答案 2 :(得分:0)
这是技术含量较低的解决方案。使用预处理器宏。
void append(std::string& s, int value);
void append(std::string& s, void* value);
#ifdef MPI_REQUEST_IS_INT
// No need to declare append() for MPI_Request
#else
void append(std::string& s, MPI_Request request);
#endif
在.cpp文件中使用相同的策略。