有没有办法用一行在同一个对象上调用多个函数?

Is there a way to call multiple functions on the same object with one line?

只是想整理一个程序,想知道是否有人可以给我一些关于在同一行上多次调用一个队列上的成员函数的语法糖。

例如,改变:

queue<int> q;
q.push(0);
q.push(1);

类似于:

q.(push(0), push(1));
//or
q.push(0).push(1);

我知道这看起来有点可笑,而且不实用。但是,如果我想像那样缩短一小部分代码,是否可以这样做?从我目前所读的内容来看,只有当函数具有非 void return 值时才能链接方法。

当然,这是一个选项:

q.push(0); q.push(1);

但我尽量避免让 q 出现两次。再次......语法糖:)

这里的目标不是初始化,而是压缩代码块中 object/container 出现的次数。我引用队列的原因是因为它是动态的。

如果您有可以修改的 class,请使函数 return 成为对自身的引用:

template<typename T>
class queue {
public:
    //...
    queue& push(T data) {
        //...
        return *this; //return current instance
    }
    //...
private:
    //...
};

那你可以做

queue<int> q;
q.push(0).push(1);

如果你做不到,那你就束手无策了。您可以围绕 class 进行包装,但为了节省几个字符,这几乎不值得。

对于 push,您可以这样做:

queue<int> q = { 0, 1 };

但这显然只适用于 push,因为在 2 次推送后队列将包含 01

你总是可以只定义一个包装器,比如

template< class Item >
void push( queue<Item>& q, std::initializer_list<Item> const& values )
{
    for( Item const& v : values ) { q.push( v ); }
}

然后这样称呼它:

push( q, {1, 2, 3} );

如果你想要的不是符号上的方便,而只是为了使用流畅的界面技术,那么如果你不能修改class,定义一个运算符:

template< class Item >
auto operator<<( queue<Item>& q, Item v )
    -> queue<Item>&
{ q.push( move( v ) ); return q; }

然后这样称呼它:

q << 1 << 2 << 3;

请务必记录您的同事试图掌握代码的过程。 :)

哦,好的,不过,如果你不能修改class,你当然可以这样做:

template< class Item >
struct Fluent
{
    queue<Item>& items;

    auto push( Item v )
        -> Fluent&
    { items.push( move( v ) ); return *this; }

    Fluent( queue<Item>& q ): items( q ) {}
};

然后这样称呼它:

Fluent( q ).push( 1 ).push( 2 ).push( 3 );

免责声明:none 编译器触及的代码。

玩得开心!

这里只是为了好玩,这里有一个小模板技巧,它提供了一种链接几乎所有方法的方法,忽略了 return 值:

// The struct providing operator()(...) so that a call is simply
// chainer_t_instance(param_for_call1)(param_for_call2)(param_for_call3);
template <typename Class, typename Method>
struct chainer_t
{
    chainer_t(Class& instance, Method&& method) :
        _instance(instance),
        _method(method)
    {}

    chainer_t(chainer_t&& chainer) :
        _instance(chainer._instance),
        _method(chainer._method)
    {}

    // Avoid copy to avoid misunderstanding
    chainer_t(const chainer_t&) = delete;    
    chainer_t& operator=(const chainer_t&) = delete;

    // Operator () takes anything
    template <typename... Types>
    chainer_t& operator()(Types&&... types)
    {
        (_instance.*_method)(std::forward<Types>(types)...);
        return *this;
    }

protected:
    Class& _instance;
    Method& _method;
};

// Just to ease the writting
template <typename Class, typename Method>
chainer_t<Class, Method> chain(Class& instance, Method&& method)
{
    using chainer = chainer_t<Class, Method>;
    return chainer(instance, std::forward<Method>(method));
}

链式调用将是:

chain(my_instance, &my_class::add)(1)(2)(3)(4);

Live example

这可能不是您要查找的内容,但请记住,C++ 不是基于行的语言(// 注释除外)。

因此,将多个简短的语句放在一行中是完全合理的。从而达到:

calling a member function on one queue multiple times on the same line.

您只需更改:

queue<int> q;
q.push(0);
q.push(1);

进入:

queue<int> q;
q.push(0); q.push(1);

不,它不会删除两次键入 q,但如果这是一个问题,我怀疑您的问题更有可能是名称过长的变量。假设是这种情况,请始终记住您可以使用引用为变量提供更简单的本地句柄:

auto &foo = a_really_long_name_for_a_queue;
foo.push(0); foo.push(1);

如果你不能修改class,你仍然可以使用逗号运算符:

#include<queue>
#include<iostream>

int main() {
    std::queue<int> q;
    (q.push(0), q).push(1);
    std::cout << q.size() << std::endl;
}
auto repeat_call = [](auto&& f){
  return y_combinate(
    [f=decltype(f)(f)](auto&& self, auto&&...args)->decltype(self){
      f( decltype(args)(args)... );
      return decltype(self)(self);
    }
  );
};

现在我们可以repeat_call( [&](int x){ q.push(x); } )(1)(0);