使用模板参数将函数分配给函数指针

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 所有 分支需要在编译时有效,但你的分支中只有一个是有效的。如果Tint,则compare = &stringComp无效。如果Tstd::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]);
    }        
}