我用C++ 11很好的新生成器和发行版生成随机值.在一个函数中,它就像一个魅力,看起来像这样:
void foo() {
mt19937 generator;
uniform_int_distribution<unsigned> distribution;
auto dice = bind(distribution, generator);
// dice() will now give a random unsigned value
}
Run Code Online (Sandbox Code Playgroud)
但是,如何将所有三个对象作为数据成员放在一个类中呢?我可以简单地编写generator和distribution作为数据成员,但是如何在dice不知道(或想知道)其确切类型的情况下创建数据成员?这令人惊讶
class X {
mt19937 generator;
uniform_int_distribution<unsigned> distribution;
decltype(bind(distribution, generator)) dice;
};
Run Code Online (Sandbox Code Playgroud)
error C2660: 'bind' : function does not take 2 arguments在Visual Studio 2013中产生错误.
试图将std :: string的向量转换为const char*的向量:
#include <algorithm>
#include <functional>
#include <string>
#include <vector>
int main(int argc, char** argv)
{
std::vector<std::string> values;
values.push_back("test1");
values.push_back("test2");
values.push_back("test3");
std::vector<const char*> c_values(values.size());
std::transform(values.begin(), values.end(), c_values.begin(), std::mem_fn(&std::string::c_str));
std::transform(values.begin(), values.end(), c_values.begin(), std::bind(&std::string::c_str, std::placeholders::_1));
std::transform(values.begin(), values.end(), c_values.begin(), [](const std::string& str) { return str.c_str(); });
return 0;
}
Run Code Online (Sandbox Code Playgroud)
使用g ++(4.7.2)进行编译时,所有三个选项都可以编译和链接.使用clang进行编译时,选项1和2无法链接,生成:
$ clang -std=c++11 -stdlib=libc++ -lc++ stringtransform.cpp
Undefined symbols for architecture x86_64:
"std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::c_str() const", referenced from:
_main in stringtransform-ff30c1.o
ld: symbol(s) not found for architecture x86_64
Run Code Online (Sandbox Code Playgroud)
我发现我需要使用lambda版本(选项3),如果我希望它使用g ++和clang在平台之间正确链接.我是否遇到了链接器错误或者clang的C++ …
我试图将成员函数作为函数指针传递,这样我就不必依赖单例或全局函数来处理Qt 5中的Qt消息。据我所知,std :: function是正确的类型,它具有正确的签名,并且bind应该允许我阻塞隐式this指针,本质上是将成员函数作为全局/非拥有函数传递出去。
void ProgramMessageHandler::setAsMessageHandlerForProgram() {
std::function<void(QtMsgType, const QMessageLogContext &, const QString &)> funcPtr;
funcPtr = std::bind(handleMessages, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
qInstallMessageHandler(funkPtr);
}
Run Code Online (Sandbox Code Playgroud)
这不会编译。我可以成功创建funcPtr变量,但是将其传递给qInstallMessageHandler函数会导致以下情况:
log\ProgramMessageManager.cpp:16: error: cannot convert 'std::function<void(QtMsgType, const QMessageLogContext&, const QString&)>' to 'QtMessageHandler {aka void (*)(QtMsgType, const QMessageLogContext&, const QString&)}' for argument '1' to 'void (* qInstallMessageHandler(QtMessageHandler))(QtMsgType, const QMessageLogContext&, const QString&)'
oldHandler = qInstallMessageHandler(hackedPointerToHandleFunction);
^
Run Code Online (Sandbox Code Playgroud)
我读过了:
使用std :: bind时从std :: function获取函数指针
但没有人帮助我。
编辑:
因此,有人说没有单例或全局功能是不可能的……但是为什么呢?具有相同签名的成员函数和全局函数之间的唯一区别是它们没有相同的签名,存在隐式this指针作为成员函数的第一个参数。 …
我目前正尝试使用功能模板std::bind创建一个std::function<void()>
template<class Iterator>
void printRange(Iterator first, Iterator last) {
std::copy(first, last, std::ostream_iterator<typename Iterator::value_type>(std::cout, " "));
std::cout << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
从概念上讲,我想要的是
int main() {
std::vector<int> v{1, 2, 3};
auto f0 = std::bind(printRange, v.begin(), v.end()); // won't compile, of course
f0();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我知道这不能编译,因此我必须实例化函数模板才能真正使用它。例如,以下替代方法将起作用:
auto f1 = std::bind(printRange<std::vector<int>::const_iterator>, v.begin(), v.end());
auto f2 = std::bind(printRange<decltype(v.begin())>, v.begin(), v.end());
auto f3 = [&v]() { printRange(v.begin(), v.end()); };
Run Code Online (Sandbox Code Playgroud)
我已经创建了一个便利功能
template<class Iterator>
std::function<void()> makePrintRangeFunction(Iterator first, Iterator last) {
return std::bind(printRange<Iterator>, first, last);
} …Run Code Online (Sandbox Code Playgroud) 我正在尝试将 std::transform 与 std::bind 一起使用来简化循环。这是一些代码:
class ITest
{
public:
virtual CPrueba Prueba(double p, double d = 0)const = 0;
};
void foo(const ITest& test)
{
std::vector<double> v;
std::vector<CPrueba> vRes;
// ...
// ...
std::transform(v.begin(), v.end(), back_inserter(vRes),
bind(&ITest::Prueba, test, _1, 0));
//...
}
Run Code Online (Sandbox Code Playgroud)
这不编译。
我正在使用 VS2008 SP1 并且我收到了很多我不明白的模板错误,所以我在 ideone (gcc 4.7.2) 中进行了尝试。在那里,我遇到了一些更具可读性的错误,我得出结论,这与 ITest 是抽象的有关。
但是我已经尝试过改变我通过测试对象的方式,如果我通过指针来做,它就可以工作。
那么有什么我可以用来保留函数签名并仍然使用带有绑定的转换而不是循环的东西吗?
据我了解,
std::bind 完美地转发它包装的可调用对象和该可调用对象的参数;std::bind返回对象本身是可移动的和/或能够复制,这取决于可调用对象和其参数是否是可移动的和/或能够复制;std::bind返回对象可以是嵌套的,在这种情况下,外部std::bind返回对象是可移动的和/或能够复制,正如结合其他可调用的对象时.因此,我希望以下代码片段可以编译好.相反,代码会在最后两个语句中生成一堆编译器错误main().
#include <functional>
template<typename HandlerType>
void call_handler(HandlerType&& handler)
{
handler();
}
template<typename HandlerType>
void do_something(HandlerType&& handler)
{
auto f = std::bind(
&call_handler<HandlerType&>,
std::forward<HandlerType>(handler));
f();
}
int main()
{
auto a = [&]() {};
do_something(a);
do_something(std::move(a));
auto b = std::bind([&]() {});
do_something(b); // <- compiler error!
do_something(std::move(b)); // <- compiler error!
}
Run Code Online (Sandbox Code Playgroud)
两个问题行中的每一个都没有出现另一个错误.为了消除所有错误,我必须注释掉这两行.
这是一个示例错误,来自Cygwin中的g ++ 4.9.2,在调用f()in do_something():
(4 of 103): error: no match for call …Run Code Online (Sandbox Code Playgroud) 读取用于C++ 17的建议有关删除标准的一些过时,旧的和未使用的部分(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4190.htm)我找到D.9部分有点奇怪:
D.9"粘合剂"[depr.lib.binders]
这定义了bind1st()/ bind2nd(),它们被bind()严格取代.(在将来,我会认为,bind()的本身已被lambda表达式,尤其是通用的Lambda表达式取代,所以绑定()应该被废弃,但不是此提案的一部分.)
我没有得到的是关于bind()自己被lambdas取代的评论.
如果我有课:
class A
{
public:
void f(int a){}
void f(int a, int b){}
}
Run Code Online (Sandbox Code Playgroud)
而且我想将一个函数指针传递A::f给某个函数,someFunction以便这个函数可以在实例化的对象上调用它A,我声明someFunction:
void someFunction(const std::function<void(int, int)>&);
Run Code Online (Sandbox Code Playgroud)
并称之为:
A a;
someFunction(std::bind(static_cast<void (A::*)(int, int)> (&A::f),
std::ref(a),
std::placeholders::_1,
std::placeholders::_2));
Run Code Online (Sandbox Code Playgroud)
如何使用lambda实现相同的功能?真的没有什么bind()可以做的,用lambda无法做到吗?
出现问题的情况
请考虑以下c ++代码:
#include <functional>
#include <iostream>
#include <string>
// Superclass
class A {
public:
virtual std::string get() const {
return "A";
}
};
// Subclass
class B : public A {
public:
virtual std::string get() const {
return "B";
}
};
// Simple function that prints the object type
void print(const A &instance) {
std::cout << "It's " << instance.get() << std::endl;
}
// Class that holds a reference to an instance of A
class State {
A &instance; …Run Code Online (Sandbox Code Playgroud) 当我想创建一个用于包装work(..)成员的std :: function时,我遇到了一个让我疲惫的编译错误.
示例代码:
class C{
public:
C(){
std::function<void(void) > f = std::bind(&C::work,
this,
std::bind(&C::step1, this),
std::bind(&C::step2, this));
QList<decltype(f)> lst;
lst.append(f);
.....
}
private:
void work(std::function<bool()> fn1, std::function<bool()> fn2 ) {
if (fn1()) {
QTimer::singleShot(1, fn2);
}
else {
QTimer::singleShot(5, fn1);
}
}
bool step1(){return true;}
bool step2(){return true;}
};
Run Code Online (Sandbox Code Playgroud)
编译错误:
main.cpp:49: erreur : conversion from 'std::_Bind_helper<false, void (C::*)(std::function<bool()>, std::function<bool()>), C* const, std::_Bind<std::_Mem_fn<bool (C::*)()>(C*)>, std::_Bind<std::_Mem_fn<bool (C::*)()>(C*)> >::type {aka std::_Bind<std::_Mem_fn<void (C::*)(std::function<bool()>, std::function<bool()>)>(C*, std::_Bind<std::_Mem_fn<bool (C::*)()>(C*)>, std::_Bind<std::_Mem_fn<bool (C::*)()>(C*)>)>}' to non-scalar type 'std::function<void()>' requested …Run Code Online (Sandbox Code Playgroud) 我发现以下代码无法编译非常令人困惑
#include <functional>
class Mountain {
public:
Mountain() {}
Mountain(const Mountain&) = delete;
Mountain(Mountain&&) = delete;
~Mountain() {}
};
int main () {
Mountain everest;
// shouldn't the follwing rvalues be semantically equivalent?
int i = ([](const Mountain& c) { return 1; })(everest);
int j = (std::bind([](const Mountain& c) {return 1;},everest))();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译错误是:
$ g++ -std=c++20 test.cpp -o test
In file included from test.cpp:1:
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/functional:486:26: error: no
matching constructor for initialization of 'tuple<Mountain>'
: _M_f(std::move(__f)), _M_bound_args(std::forward<_Args>(__args)...)
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~ …Run Code Online (Sandbox Code Playgroud)