是否可以获取内置标准运算符的函数指针

Is it possible to get the function pointer of a built-in standard operator?

本文关键字:运算符 函数 指针 标准 内置 获取 是否      更新时间:2023-10-16

我想引用内置运算符的函数指针,但我不知道如何指定特定类型的重载。

我有以下模板类签名:

template<typename ParamsType, typename FnCompareType>
class MyAction
{
public:
    MyAction(ParamsType& arg0, ParamsType& arg1, FnCompareType& fnCpmpare) 
    : arg0_(arg0), arg1_(arg1), fnCompare_(fnCpmpare) {}
    bool operator()()
    {
        if((*fnCompare_)(arg0_,arg1_)
        {
            // do this
        }
        else
        {
            // do s.th. else
        }
    }
private:
    ParamsType& arg0_;
    ParamsType& arg1_;
    FnCompareType& fnCompare_;
}

想要使用这样的语法:

void doConditional(int param1, int param2)
{
    MyAction<int,&::operator>=> action(param1,param2);
    if(action())
    {
        // Do this
    }
    else
    {
        // Do that
    }
}

但这并不能编译:

error: ‘::operator>=’ has not been declared

我能做些什么来引用这种内在的静态操作?

内置运算符

为什么不能有它们的函数指针:

C++11,§13.6/1,[过度构建]

本款规定了代表第5条中定义的内置运算符的候选运算符函数。这些候选函数参与13.3.1.2中所述的操作员过载解决过程,并且不用于其他目的

内置运算符(用于内置类型的运算符)不是真正的运算符函数。所以不能让函数指针指向它们。您也不能使用operator<(A,B)语法调用它们。它们只参与重载解析,但编译器将直接将它们转换为适当的asm/machine指令,而不需要任何类型的"函数调用"。

解决此问题的方法:

user1034749已经回答了这个问题,但为了完整起见:

该标准在§20.8,[function.objects]中定义了许多功能对象,即

  • 算术运算
  • 比较
  • 逻辑运算
  • 逐位操作

函数对象是一个函数对象类型的对象。在期望将指向函数的指针传递给算法模板的地方(第25条),接口被指定为接受函数对象。这不仅使算法模板能够使用指向函数的指针,还使它们能够使用任意函数对象。

C++11,§20.8.5,[比较]

  • 等于
  • 不合格
  • 更大,更小
  • 较大_相等
  • less_equal

这些是模板化的函数对象,在它们的operator()函数中衰减为类似的运算符。它们可以用作函数指针参数。

user1034749是对的,我想声明:没有其他方法,它们在用法上完全等同于"原始"函数指针给出参考。

标准类类型运算符

您可以使用标准库运算符作为函数指针(以"实际函数"的形式存在)。

但是您必须引用模板的相应实例。编译器将需要适当的提示来推导正确的模板。

这适用于我在MSVC 2012上使用std::basic_stringoperator+

template<class Test>
Test test_function (Test const &a, Test const &b, Test (*FPtr)(Test const &, Test const &))
{
   return FPtr(a, b);
}
int main(int argc, char* argv[])
{
   typedef std::char_traits<char> traits_t;
   typedef std::allocator<char> alloc_t;
   std::basic_string<char, traits_t, alloc_t> a("test"), b("test2");
   std::cout << test_function<std::basic_string<char, traits_t, alloc_t>>(a, b, &std::operator+) << std::endl;
   return 0;
}

如果test_function的模板参数被排除在外进行推导,这将失败(至少对于MSVC 2012)。

您可以使用与C++标准库中使用的解决方案相同的解决方案:

std::sort (numbers, numbers+5, std::greater<int>());

其中越大

template <class T> struct greater : binary_function <T,T,bool> {
    bool operator() (const T& x, const T& y) const {return x>y;}
};

就你而言http://www.cplusplus.com/reference/functional/greater_equal/

关于已生成运算符的引用。

您可以引用现有的运算符<对于任何类(当然,如果它们不是私有的、受保护的或您的类/函数不是朋友)。但是运营商<对于内置类型(bool、short、int、double),这是不可能的引用。事件如果不看C++标准,你可以从我上面的文本中看到。

fghj提供的解决方案的一个扩展,适用于赋值类型运算符,如+=/-=等,将类似于标准变体来包装这些运算符。然后你可以做:

#include <iostream>
template <typename T>
struct assign_plus {
    void operator() const (T& a, const T& b){
        a += b;
    }
};
template <typename T>
struct assign_minus {
    void operator() const (T& a, const T& b){
        a -= b;
    }
};

template<template <class T> class O> requires requires(int& a, const int& b){
    { O<int>{}(a,b) };
}
void example(int& a, const int& b){
    O<int>{}(a,b);
}
int main(){
    int a = 5;
    int b = 6;
    example<assign_plus>(a,b);
    std::cout << a << "n";
    example<assign_minus>(a,b);
    std::cout << a << "n";
    return 0;
}

其中在给定CCD_ 8兼容性的情况下可以保持/去除约束。然后,这些约束也可以扩展为要求a += b是有效的(例如,对于自定义类型)。