繁体   English   中英

使用std :: tr1 :: bind与std :: vector :: push_back

[英]Using std::tr1::bind with std::vector::push_back

为什么我的VS2010无法编译此代码:

#include <functional>
#include <vector>
int main()
{
    std::vector<int> vec;
    std::bind(&std::vector<int>::push_back, std::ref(vec), 1)();
    return 0;
}

您应该更具体地说明为什么这似乎不适合您。

#include <iostream>
#include <tr1/functional>
#include <vector>

int main(int argc, char* argv[]) {
    std::vector<int> vec;
    std::tr1::bind(&std::vector<int>::push_back, std::tr1::ref(vec), 1)();
    std::cout << "vec.size = " << vec.size() << std::endl;
    std::cout << "vec[0] = " << vec[0] << std::endl;
    return 0;
}

$ gcc -o test -lstdc++ test.cpp && ./test
vec.size = 1
vec[0] = 1

更新: Luc Danton是对的,这里的问题是重载的push_back 请参阅问题VS2010是否存在boost :: bind问题? 另请注意,问题不仅限于push_back ,请参阅Visual Studio 2010和boost :: bind

最重要的是,您在便携式 C ++中无法实现的目标。 std::vector<>::push_back在C ++ 11编译器中过载,因为至少必须有lvalues的重载和rvalues的重载。

通常 ,当获取重载成员函数的地址时,C ++ 11 FDIS中的§13.4/ 1告诉我们,我们可以控制我们正在采用的地址:

在某些上下文中,使用不带参数的重载函数名称解析为函数,指向函数的指针或指向来自重载集的特定函数的成员函数的指针。 函数模板名称被认为是在这种上下文中命名一组重载函数。 选择的函数是其类型与上下文中所需的目标类型的函数类型相同的函数。 [ 注意:也就是说,当匹配指向成员函数的指针类型时,忽略函数所属的类。 - 尾注 ]目标可以

  • 正在初始化的对象或引用,
  • 作业的左侧,
  • 一个函数的参数,
  • 用户定义的运算符的参数,
  • 函数,运算符函数或转换的返回值,
  • 显式类型转换 ,或
  • 非类型模板参数。

重载的函数名称可以在&运算符之后。 如果没有参数,则不应在除列出的上下文之外的上下文中使用重载的函数名称。 [ 注意:忽略重载函数名称周围的任何冗余括号。 - 尾注 ]

问题来自§17.6.5.5/ 2:

实现可以通过向成员函数签名添加具有默认值的参数来在类中声明其他非虚拟成员函数签名; 因此,C ++标准库中类的成员函数的地址具有未指定的类型。

因此,永远不能获取标准库类成员函数的地址,因为这样的表达式的类型根据定义是不可知的,除了在逐个实现的基础上。

Luc Danton建议的解决方法(特别是使用lambda)也是我推荐的:

std::vector<int> vec;
[&](){ vec.push_back(1); }();

尝试这个:

struct push_back {
    void
    operator()(std::vector<int>& vector, int i) const
    {
        vector.push_back(i);
    }
};

// somewhere else:
std::vector<int> vec;
std::tr1::bind(push_back(), std::tr1::ref(vec), 1)();

用C ++ 03注意push_back不能是本地类型; 使用C ++ 11它可以但是使用lambda会更加惯用(并且完全等效)。

在所有可能性中,您的实现为std::vector<T>::push_back提供重载,因此必须消除其地址的歧义。 如果发生这种情况,您的编译器应该已经为您提供了相应的错误消息。 所有情况下,你应该通过“它不可能”来解释你的意思。


关键是不要使用这样的辅助函数。 - 洋红色

那你为什么不把它放在这个问题上呢? 我无法理解你的想法。

你也可以试试这个:

std::vector<int> vec;
void (std::vector<int>::*push_back)(int const&) = &std::vector<int>::push_back;
std::tr1::bind(push_back(), std::tr1::ref(vec), 1)();

我认为不能保证成功。

它应该像这样:

std::vector<int> vec;
std::tr1::bind(&std::vector<int>::push_back, std::tr1::ref(vec), _1)(1);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM