有条件地启用非模板函数 c++
Conditionally enable non-template function c++
>Background
我正在使用 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
不同?
这很不幸。底线是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);
完整的示例,您甚至可以看到哪个cout
行内联到 main 中。
您可以使用默认模板参数使其成为函数模板,这允许 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);
}
演示
这是一个低技术解决方案。使用预处理器宏。
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文件中使用相同的策略。
相关文章:
- "error: no matching function for call to"构造函数错误
- 什么时候调用组成单元对象的析构函数
- 继承函数的重载解析
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- C++模板来检查友元函数的存在
- 递归函数计算序列中的平方和(并输出过程)
- 对RValue对象调用的LValue ref限定成员函数
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 为什么使用 "this" 指针调用派生成员函数?
- 将对象数组的引用传递给函数
- 函数调用中参数的顺序重要吗
- 函数向量_指针有不同的原型,我可以构建一个吗
- 使用不带参数的函数访问结构元素
- 代码在main()中运行,但在函数中出现错误
- 内置函数可查看CPP中的成员变量
- 如何获取std::result_of函数的返回类型
- 如何在c++中为模板函数实例创建快捷方式
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗