C ++ 11 std :: forward一个指针 [英] C++11 std::forward a pointer
问题描述
我在应用程序中有一个信号
类,为类提供了暴露事件的选项(与.NET中相同)。
I have a Signal
class in my application that provides classes with an option to expose events (same as in .NET).
这个班的工作和一切都很好。
The class works and all is well.
昨天我看到这个SO问题(及其答案),并熟悉 std :: forward
。
Yesterday I saw this SO question (and its answer) and was familiarized with std::forward
.
我决定尝试在我的代码中使用它,所以我改变每个 std :: function< void(Args ...)>
到 std :: function< void(Args& ...)>
运算符())我使用了上面链接中看到的相同的逻辑,所以现在函数 Args& ... args
回调使用 std :: forward< Args>(args)...
I decided to try to use it in my code so I changed every std::function<void(Args...)>
to std::function<void(Args&&...)>
and in the raise function (the operator()
) I used the same logic I saw in the above link so now the function takes Args&&...args
and the callback uses std::forward<Args>(args)...
类(有一些更改,使它成为一个很好的例子):
Here's a simplified version of my Signal class (with some changes to make it a good example):
template<typename... Args> class Signal
{
public:
int operator+=(const std::function<void(Args&&...)>& func) {
int token = getNewToken();
m_subscribers.emplace(token, func);
return token;
}
void operator()(Args&&... args) {
for (auto it : m_subscribers) {
it.second(std::forward<Args>(args)...);
}
}
private:
std::map<int, std::function<void(Args&&...)>> m_subscribers;
};
int main() {
int* six = new int(6);
int seven = 7;
Signal<int*> e1;
e1 += [](int* x) { std::cout << *x; };
Signal<int> e2;
e2 += [](int x) { std::cout << x; };
e1(&seven);
e2(6);
e1(six); //Error C2664 'void Signal<int *>::operator ()(int *&&)':
// cannot convert argument 1 from 'int *' to 'int *&&'
e1(std::move(six)); //This is a workaround
return 0;
}
我看到的问题是类(或 main
在这个例子中)尝试用指针引发事件,我不知道如何解决这个。
The issue I'm seeing is with classes (or main
in this example) that try to raise events with pointers and I'm not sure how to solve this.
我的主要目标是如果开发人员选择使用 Signal
std :: move
。
My main goal is to have the Signal class a general API and if the developers chose to use Signal<int*>
I don't want him\her to raise with std::move
.
我在这里做错了什么?
推荐答案
T&&&
非cv限定函数模板参数。在您的调用操作符中:
T&&
is only a universal reference if T
is a non-cv-qualified function template parameter. In your call operator:
void operator()(Args&&... args) {
Args
不是函数的模板参数,它是一个模板参数的类。因此对于 Signal
。因为运算符()
int * six
是一个左值,所以失败。
Args
isn't a template parameter of the function, it's a template parameter of the class. So for Signal<int*>
, this operator()
takes an rvalue reference to int*
. Since six
is an lvalue, that fails.
你想要的是提供正确的参考资格到信号
。像这样:
What you want is to provide the correct reference qualifications to Signal
. Like so:
template<typename... Args>
class Signal
{
using F = std::function<void(Args...)>; // NB: Just Args...
public:
int operator+=(F func) {
int token = getNewToken();
m_subscribers.emplace(token, std::move(func));
return token;
}
void operator()(Args... args) { // NB: just Args...
for (auto& it : m_subscribers) { // NB: auto&
it.second(args...);
}
}
private:
std::map<int, F> m_subscribers;
};
请注意,转发 Args ...
可疑。如果你有两个订阅者怎么办?一旦你转发参数,一旦你不能真正使用他们第二次。
Note that forwarding Args...
is questionable anyway. What if you had two subscribers? Once you forward the args once you can't really use them a second time.
以上将使信号< int *>
运算符()
只需要一个 int *
,你可以传递一个左值或右值。
The above will make Signal<int*>
do what you expect. The operator()
will just take an int*
, which you can pass either an lvalue or an rvalue to.
这篇关于C ++ 11 std :: forward一个指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!