使用模板参数将函数分配给函数指针
Assigning function to function pointer with template parameter
所以我有这两个功能:
bool intComp(int a, int b)
{
return a > b;
}
bool stringComp(std::string a, std::string b)
{
return strcmp(a.c_str(), b.c_str()) > 0;
}
在我的排序函数中,我想分配 stringComp 或 intComp 函数:
template<typename T>
void sort(std::vector<T>& vector)
{
bool (*compare)(T a, T b);
if (typeid(T) == typeid(int))
{
compare = &intComp;
}
else if (typeid(T) == typeid(std::string))
{
compare = &stringComp;
}
...
}
当我使用 compare = &stringComp
删除 else if 块时,分配和排序工作正常。但是,一旦我尝试使用 int
以外的类型(例如字符串)分配函数,我就会收到以下编译器错误: '=': cannot convert from 'bool (__cdecl *)(std::string,std::string)' to 'bool (__cdecl *)(T,T)'
我做错了什么?为什么代码适用于 int 但不适用于其他类型?模板是否可以在类似于枚举的情况下使用整数,这就是为什么我可以毫无问题地分配 intComp 函数的原因?
问题是正常 if
的 所有 分支需要在编译时有效,但你的分支中只有一个是有效的。如果T
为int
,则compare = &stringComp
无效。如果T
为std::string
,则compare = &intComp
无效。
相反,您需要 if constexpr
,它在 C++17 中引入并在编译时进行比较。它会丢弃不需要的分支,只要它依赖于模板参数即可,因此它们是否对该类型没有意义也没关系。例如:
template <typename T>
void sort(std::vector<T>& vector)
{
bool (*compare)(T a, T b);
if constexpr (std::is_same_v<T, int>) {
compare = &intComp;
} else if constexpr (std::is_same_v<T, std::string>) {
compare = &stringComp;
} else {
// Error
}
// ...
}
在 C++17 中,如果满足以下条件,您可以使用 constexpr:
#include <string>
#include <vector>
#include <typeinfo>
bool intComp(int a, int b) { return a < b; }
bool stringComp(std::string a, std::string b) { return a < b; }
template<typename T>
void sort(std::vector<T>& vector)
{
bool (*compare)(T a, T b);
if constexpr (typeid(T) == typeid(int))
{
compare = &intComp;
}
else if (typeid(T) == typeid(std::string))
{
compare = &stringComp;
}
}
之前,我实际上在 C++17 及更高版本中使用它,您可以让重载解析选择正确的函数:
#include <string>
#include <vector>
#include <iostream>
bool Comp(int a, int b) { return a < b; }
bool Comp(std::string a, std::string b) { return a < b; }
template<typename T>
void sort(std::vector<T>& vector)
{
if (vector.size() > 1) {
std::cout << Comp(vector[0],vector[1]);
}
}
所以我有这两个功能:
bool intComp(int a, int b)
{
return a > b;
}
bool stringComp(std::string a, std::string b)
{
return strcmp(a.c_str(), b.c_str()) > 0;
}
在我的排序函数中,我想分配 stringComp 或 intComp 函数:
template<typename T>
void sort(std::vector<T>& vector)
{
bool (*compare)(T a, T b);
if (typeid(T) == typeid(int))
{
compare = &intComp;
}
else if (typeid(T) == typeid(std::string))
{
compare = &stringComp;
}
...
}
当我使用 compare = &stringComp
删除 else if 块时,分配和排序工作正常。但是,一旦我尝试使用 int
以外的类型(例如字符串)分配函数,我就会收到以下编译器错误: '=': cannot convert from 'bool (__cdecl *)(std::string,std::string)' to 'bool (__cdecl *)(T,T)'
我做错了什么?为什么代码适用于 int 但不适用于其他类型?模板是否可以在类似于枚举的情况下使用整数,这就是为什么我可以毫无问题地分配 intComp 函数的原因?
问题是正常 if
的 所有 分支需要在编译时有效,但你的分支中只有一个是有效的。如果T
为int
,则compare = &stringComp
无效。如果T
为std::string
,则compare = &intComp
无效。
相反,您需要 if constexpr
,它在 C++17 中引入并在编译时进行比较。它会丢弃不需要的分支,只要它依赖于模板参数即可,因此它们是否对该类型没有意义也没关系。例如:
template <typename T>
void sort(std::vector<T>& vector)
{
bool (*compare)(T a, T b);
if constexpr (std::is_same_v<T, int>) {
compare = &intComp;
} else if constexpr (std::is_same_v<T, std::string>) {
compare = &stringComp;
} else {
// Error
}
// ...
}
在 C++17 中,如果满足以下条件,您可以使用 constexpr:
#include <string>
#include <vector>
#include <typeinfo>
bool intComp(int a, int b) { return a < b; }
bool stringComp(std::string a, std::string b) { return a < b; }
template<typename T>
void sort(std::vector<T>& vector)
{
bool (*compare)(T a, T b);
if constexpr (typeid(T) == typeid(int))
{
compare = &intComp;
}
else if (typeid(T) == typeid(std::string))
{
compare = &stringComp;
}
}
之前,我实际上在 C++17 及更高版本中使用它,您可以让重载解析选择正确的函数:
#include <string>
#include <vector>
#include <iostream>
bool Comp(int a, int b) { return a < b; }
bool Comp(std::string a, std::string b) { return a < b; }
template<typename T>
void sort(std::vector<T>& vector)
{
if (vector.size() > 1) {
std::cout << Comp(vector[0],vector[1]);
}
}