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

Posted

技术标签:

【中文标题】是否可以获得内置标准运算符的函数指针?【英文标题】:Is it possible to get the function pointer of a built-in standard operator? 【发布时间】:2013-07-12 18:16:09 【问题描述】:

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

我有以下模板类签名:

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

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

【问题讨论】:

ACTION_P1(MyAction,fnCompare) ... 这还能编译吗?返回类型和参数的类型在哪里? @MonadNewb 是的,确实如此!真正的定义更加复杂。 googlemock 通过模板参数列表延迟操作参数的类型。 感谢您删除 googlemock 的详细信息,以使您的问题更清楚。为了将来参考,当您进行这种简化以解决问题的核心问题时,您应该制作一个使用纯 C++ 编译的示例,以便其他人可以复制和粘贴代码并按原样编译。 @MonadNewb 我认为pixelchemist 的回答非常适合回答有关该主题的规范问题。应该改变什么以使这个问题成为一个规范的问题,或者已经存在。类似的问题? 是的,pixelchemist 给出了一个非常彻底和完整的答案。 IMO,您应该修改您的示例代码,以便在不依赖任何第三方库的情况下进行编译。从我阅读您的代码的方式来看,ACTION_P1 应该是一个函数名。但是,我没有看到返回类型。而且它的参数只有名字,没有类型。 【参考方案1】:

您可以使用与 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/

关于内置运算符的引用。

您可以为任何类引用现有的运算符

【讨论】:

谢谢!已经找到了如何使用它。抱歉,如果可以以某种方式引用这些运算符函数,我已经编辑了我的问题以获得一般性答案。 @g-makulik 标准库提供了封装了大多数内置运算符的命名函数。 @g-makulik 我想我不明白你在寻找什么样的“一般答案”。您可以通过标准库给出的名称来引用“运算符函数”。 @MonadNewb 再次:我知道。但这些与“原始”函数指针有点不同,不是吗?这些是具有适当operator() 定义的结构,您需要一个实例来调用它们。 在 C++11 中,您可以使用 lambda 函数,而无需使用 opeator() 定义新结构【参考方案2】:

内置运算符

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

C++11,§13.6/1,[over.built]

代表第 5 条中定义的内置运算符的候选运算符函数在本小节中指定。这些候选函数参与运算符重载决议过程,如 13.3.1.2 中所述并且不用于其他目的

内置运算符(用于内置类型的运算符)不是真正的运算符函数。所以你不能让函数指针指向它们。您也不能使用operator&lt;(A,B) 语法调用它们。 它们只参与重载解析,但编译器会将它们直接翻译成适当的 asm/机器指令,而不需要任何类型的“函数调用”。

解决这个问题的方法:

user1034749 has already answered这个问题,但为了完整性:

标准在§20.8,[function.objects]中定义了很多函数对象,即

算术运算 比较 逻辑运算 按位运算

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

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

equal_to not_equal_to 更大,更少 greater_equal less_equal

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

user1034749 是对的,我想说:没有其他办法,这些在用法上完全等同于“原始”函数指针。给出了参考。

标准类类型运算符

您可以将标准库运算符用作函数指针(以“真实函数”的形式出现)。

但您必须参考相应的模板实例。编译器将需要适当的提示来推断出正确的模板。

这适用于我在 MSVC 2012 上使用 operator+ of std::basic_string

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)。

【讨论】:

这看起来很像这个问题的规范答案!

以上是关于是否可以获得内置标准运算符的函数指针?的主要内容,如果未能解决你的问题,请参考以下文章

strlen()函数和sizeof算符

是否传递指针参数,在 C++ 中按值传递?

为对象指针实现复制构造函数和运算符的正确方法是啥

指针,数组指针,指针数组,函数指针解析

指针,数组指针,指针数组,函数指针解析

C-函数,数组指针,指针之间的运算