C++ C++;函数将重复参数绑定到curried函数

C++ C++;函数将重复参数绑定到curried函数,c++,gcc,currying,C++,Gcc,Currying,我试图理解curry和调用一个函数的概念,该函数包含三个字符串,但只传递两个字符串,并使用第二个参数两次 但是,当我这样做时,第二个参数根本不会被发送到函数,它会打印出一个空字符串。这真的是一个明显的错误吗 string concatthreestrings(string a,string b,string c){ cout<<"Value of A: "<<a<<endl; cout<<"Value of B: "<<

我试图理解curry和调用一个函数的概念,该函数包含三个字符串,但只传递两个字符串,并使用第二个参数两次

但是,当我这样做时,第二个参数根本不会被发送到函数,它会打印出一个空字符串。这真的是一个明显的错误吗

string concatthreestrings(string a,string b,string c){
    cout<<"Value of A: "<<a<<endl;
    cout<<"Value of B: "<<b<<endl;
    cout<<"Value of C: "<<c<<endl;
    return a+b+c;
}


int main()
{
    typedef std::function< string( string,string) > fun_t ;
    using namespace std::placeholders;
    fun_t fn = std::bind( concatthreestrings, _1, _2, _2);
    cout<<endl<<fn( "First","Second")<<endl;

}
string concatthrestrings(字符串a、字符串b、字符串c){

cout复制字符串很昂贵。因为
std::bind
认为占位符的值只使用一次,所以它对字符串执行
std::move
。这是对每个参数执行的,因此,
b
c
都是移动的,这意味着空字符串

您可以通过显式地说出您的意思,通过常量引用传递参数来更改该行为:

string concatthreestrings(string const& a,string const& b,string const& c)

现在,它应该可以工作了。

我使用这个小示例进行了一些测试,它展示了与您相同的行为:

#include <functional>
#include <iostream>
#include <string>

using std::string;

void print(string s1, string s2)
{
    std::cout << s1 << s2 << '\n';
}

int main()
{
    using namespace std::placeholders;

    typedef std::function< void(string) > fn_t;

    fn_t func = std::bind(print, _1, _1);

    std::string foo("foo");
    func(foo);
}

// outputs: foo
另一种解决方案是替换typedef,以便
func
通过引用const获取其参数:

typedef std::function< void(string const &) > fn_t;
typedef std::functionfn\t;
我真的不明白为什么另一个typedef不起作用……可能字符串被移动了,正如@ipc所指出的,但我不知道这是在什么时候发生的。我甚至不确定这是标准行为,因为
函数
绑定
返回的包装器都应该使用完美的转发设计一些优化,当包装参数按值传递时移动包装参数

编辑


我做了一些测试,结果是GCC的
std::function
实现对其参数执行了移动,而
std::bind
返回的包装器则没有。我仍然不知道这是否是标准的,我将就此写一个问题。

非常有趣的问题,我不会期望出现这种行为!只是添加som更正:这不是真正的curry。绑定参数和curry是两个非常相似但仍然不同的操作,不应混淆。curry意味着取一个函数,该函数取N个参数的函数,并将其转换为一个参数的函数,该函数返回一个参数的函数,该函数返回一个argu的函数ment…(重复n次)。您可以使用
std::bind
来实现
curry
函数,该函数可以为您实现这一点(在某种程度上)。类似地,您可以使用currying以
std::bind
@LiKao的方式实现参数绑定:
bind
allow,而不是currying。感谢LiKao和Luc,我现在明白了区别。我的印象是,在这个特定的示例中,bind被用来对another@LiKao卢克·图莱尔:这是avior似乎不在VC++编译器中出现。看起来它是一个GCC特性。你确定这个行为定义得很好吗?从我在标准中读到的内容来看,
bind
返回的包装器将其参数转发给包装的函数。在这种情况下,根据我的理解,我们将有一个这样的包装器(推导模板参数并折叠后):
string g(const char(&u1)[6],const char(&u2)[7]){concatthrestrings(forward(u1),forward(u2),forward(u2));}
。三个字符串
a
b
c
将从数组中构造,因此我看不出移动会发生在哪里。@ipc:有什么方法可以在std::bind中指定此行为,而不是更改函数定义吗?它自己访问移动的对象是UB.ya我想它是编译器实现的因为VC没有展示它,所以出现了离子问题。
typedef std::function< void(string const &) > fn_t;