【问题标题】:Why functional objects in C++ for arithmetic operations are implemented as templates?为什么 C++ 中用于算术运算的函数对象被实现为模板?
【发布时间】:2021-02-07 04:07:19
【问题描述】:

我想知道,为什么 c++ 中的函数对象被实现为模板化,而自 c++14 以来,void 是默认类型。

例如:

当被operator()调用时,这个对象实际上执行算术运算+-*/

operator() 必须是模板才能使用不同的类型作为参数,但为什么必须是结构?

编辑

我可以创建一个运算符std::plus<>,它可能适用于operator() 中的不同类型:

struct Foo{
    int foo;
};

Foo operator+(const Foo& lhs, const Foo& rhs){
    return {2 * lhs.foo + 3 * rhs.foo};
}

std::ostream& operator<<(std::ostream& os, const Foo& f){
    std::cout << f.foo;
    return os;
 }

int main()
{
    auto op = std::plus<>();
    std::cout << op(5, 3) << "\n";
    std::cout << op(3.14, 2.71) << "\n";
    std::cout << op(Foo(2), Foo(3)) << "\n";
}

这给出了预期的输出。或者可能是这样,在最初指定类型后,您会得到更优化的东西?

【问题讨论】:

    标签: c++ operators arithmetic-expressions


    【解决方案1】:

    这是一种设计选择。如果您指定类型,则没有模板operator(),而是整个类都是模板。 operator() 就像

    constexpr T operator()(const T &lhs, const T &rhs) const 
    {
        return lhs + rhs;
    }
    

    这与使用模板 operator() 在几个方面不同。

    如果我们传递一个std::plus&lt;int&gt;,它是专门针对ints 的加号函子,仅此而已。

    如果我们改为传递std::plus&lt;&gt; 而不指定类型,它将有一个模板化的operator()。该函子可以将其 operator() 应用于任何有效类型。

    从头顶限制类型的一些好处:

    由于指定了类型,仿函数可以毫无问题地处理隐式转换。

    你知道函子不会默默地做我们不希望它做的事情。它只会在Ts 上添加。

    编辑

    一些行为不同的例子。

    #include <iostream>
    #include <functional>
    #include <string>
    
    struct Foo {};
    
    
    int main()
    {
        auto stringadd = std::plus<std::string>{};
        auto anyadd = std::plus<>{};
    
        std::cout << stringadd("hey ", "you") << '\n';
        //std::cout << anyadd("hey ", "you") << '\n'; // error: no match for call to '(std::plus<void>) (const char [5], const char [4])'
    
        //std::cout << stringadd("hey ", 1) << '\n'; // error: no match for call to '(std::plus<std::__cxx11::basic_string<char> >) (const char [5], int)'
        std::cout << anyadd("hey ", 1) << '\n';
    }
    

    【讨论】:

    • @spiridon_the_sun_rotator 我不太明白编辑的重点。我已经解决了行为不同的事实以及一些原因的例子。这与优化无关。它是关于函子如何与其他代码交互的。
    猜你喜欢
    • 2014-04-30
    • 2013-01-08
    • 1970-01-01
    • 1970-01-01
    • 2020-08-14
    • 1970-01-01
    • 2016-05-08
    • 2021-04-08
    • 1970-01-01
    相关资源
    最近更新 更多