【问题标题】:More than one round bracket in function call?函数调用中有多个圆括号?
【发布时间】:2017-05-24 07:01:45
【问题描述】:

我有一个练习,我需要编写一个函数。功能方案看起来像

auto add(int a){
}

我需要能够用很多括号调用这个函数:

add(1)(2)(3); // 6
add(1)(2)(3)(4); // 10
add(1)(2)(3)(4)(5); // 15

但我不知道在这种情况下我应该使用哪个 C++ 功能。我听说我应该使用仿函数,但我不知道在这种情况下这是否是最好的主意。

【问题讨论】:

  • 你想做什么?为什么你认为你需要这样称呼它?
  • 你可以返回一个指向自身的函数指针
  • @M.M 函数指针不起作用 - 它必须在某处保持状态。
  • @M.M:Herb Sutter 有一个旧的“本周大师”专栏证明你做不到。你甚至不能声明那个函数:它的签名由它的参数和它的返回类型组成,它的返回类型必须包含签名。这就是无限递归。
  • @MSalters O rly?

标签: c++ c++11 c++14 currying


【解决方案1】:

您可以通过让add 返回一个functor 来做到这一点,即实现operator() 的对象。您可以编写一个模板版本,让编译器推断类型。试试看here

template <class T>
struct adder 
{
    T val;

    adder(T a) : val(a) {}

    template <class T2>
    auto operator()(T2 a) -> adder<decltype(val + a)> { return val + a; }

    operator T() const { return val; }
};

template <class T>
adder<T> add(T a)
{
    return a;
}

示例

在本例中,T 最终将解析为 double

std::cout << add(1)(2.5)(3.1f)(4) << std::endl;
// T is int -----^
// T is double ------^
// T is still double -----^
// T is still double ----------^

这是另一个示例,T 将解析为 double

std::cout << add(1)(2.5f)(3.1)(4) << std::endl;
// T is int -----^
// T is float -------^
// T is double ------------^
// T is still double ----------^

显式构造函数

如果您希望adder 的构造函数为explicit,您还必须稍微更改返回语句。

template <class T>
struct adder 
{
    T val;

    explicit adder(T a) : val(a) {}

    template <class T2>
    auto operator()(T2 a) -> adder<decltype(val + a)>
    {
        return adder<decltype(val + a)>(val + a);
    }

    operator T() const { return val; }
};

template <class T>
adder<T> add(T a)
{
    return adder<T>(a);
}

【讨论】:

  • 我会让构造函数explicit 消除歧义
  • 当然,这也会稍微改变一些返回语句。 @Mot
  • @Motti 我添加了一个使用explicit 构造函数的示例。但我想不出一个需要explicit 构造函数的好例子。
  • @Jonas,我也想不通,如果 adder&lt;T&gt; 是从外部使用的 add,那么展示这种情况会更容易。
  • 如何使用 JavaScript 执行相同的操作。如果可以,请提供帮助。
【解决方案2】:

我想到的唯一解决方案是将此“添加”作为带有重载括号运算符的类对象,它将返回新对象,然后从中调用新括号,但您需要从中返回最终值不知何故,就像一些吸气剂功能。

class Adder{

private:
    int value;
public:
    Adder():value(0){}
    Adder(int a):value(a){}
    int get(){return value;}
    Adder operator() (int a) {
        return Adder(value+a);
    }
};

但这似乎不是什么有用的东西,可能有更好的方法来完成你想要的。

【讨论】:

  • 你应该添加 operator int() {return value;}
猜你喜欢
  • 1970-01-01
  • 2020-09-11
  • 2020-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多