Slot Arguments (Beginner)
插槽的參數(shù)(初級(jí))
Signals can propagate arguments to each of the slots they call.For
instance, a signal that propagates mouse motion events mightwant to
pass along the new mouse coordinates and whether the mousebuttons are
pressed.
信號(hào)可以向它們調(diào)用的每個(gè)插槽傳遞參數(shù)。例如,一個(gè)傳遞鼠標(biāo)移動(dòng)事件的信號(hào)可能要傳入新的鼠標(biāo)坐標(biāo)以及是否按了鼠標(biāo)鍵。
As an example, we'll create a signal that passes twofloat arguments to its slots. Then we'll create a fewslots that print the results of various arithmetic operations onthese values.
作為一個(gè)例子,我們將創(chuàng)建一個(gè)信號(hào),它將傳入兩個(gè)float 參數(shù)到它的插槽。然后我們將創(chuàng)建幾個(gè)插槽,它們將打印對(duì)這兩個(gè)參數(shù)進(jìn)行算術(shù)運(yùn)算的各種結(jié)果。
void print_sum(float x, float y)
{
std::cout << "The sum is " << x+y << std::endl;
}
void print_product(float x, float y)
{
std::cout << "The product is " << x*y << std::endl;
}
void print_difference(float x, float y)
{
std::cout << "The difference is " << x-y << std::endl;
}
void print_quotient(float x, float y)
{
std::cout << "The quotient is " << x/y << std::endl;
}
This program will print out the following:
該程序?qū)⒋蛴≥敵鋈缦拢?/p>
The sum is 8
The product is 15
The difference is 2
The quotient is 1.66667
So any values that are given to sig
when it iscalled like a function are passed to each of the slots. We
have todeclare the types of these values up front when we create
thesignal. The type boost::signal<void (float,float)> means that the signal has a voidreturn value and takes two float values. Any slotconnected to sig must therefore be able to take twofloat values.
當(dāng)像函數(shù)一樣調(diào)用 sig 時(shí),輸入它的任何值都傳給了每一個(gè)插槽。創(chuàng)建信號(hào)時(shí),我們必須預(yù)先聲明這些值的類型。類型 boost::signal<void (float,float)> 表明信號(hào)具有 void返回值并接受兩個(gè) float 值。因此任何連接到sig的插槽都必須能夠接受兩個(gè)float 值。
Signal Return Values (Advanced)
信號(hào)返回值(高級(jí))
Just as slots can receive arguments, they can also returnvalues.
These values can then be returned back to the caller of thesignal
through a combiner. The combiner is a
mechanismthat can take the results of calling slots (there many be
noresults or a hundred; we don't know until the program runs)
andcoalesces them into a single result to be returned to the caller.The
single result is often a simple function of the results of theslot
calls: the result of the last slot call, the maximum valuereturned by
any slot, or a container of all of the results are somepossibilities.
正如插槽可以接收參數(shù),它們也可以返回值。然后這些值可以通過(guò)合并器(combiner)返
回給信號(hào)的調(diào)用者。合并器是這樣一種工具,它接收插槽調(diào)用的結(jié)果(可能沒有結(jié)果,也可能有100個(gè)結(jié)果;程序運(yùn)行時(shí)才知道),并且把它們合并成單一的結(jié)果
返回給調(diào)用者。該單一的結(jié)果往往是插槽調(diào)用結(jié)果的一個(gè)簡(jiǎn)單函數(shù),可能是:最后的插槽調(diào)用的結(jié)果、所有插槽返回值的最大值,或包含所有結(jié)果的容器。
We can modify our previous arithmetic operations exampleslightly so
that the slots all return the results of computing theproduct,
quotient, sum, or difference. Then the signal itself canreturn a value
based on these results to be printed:
我們可以稍微修改前面的算術(shù)運(yùn)算的例子,使插槽分別返回加減乘除的計(jì)算結(jié)果。然后信號(hào)本身就可以根據(jù)這些結(jié)果返回一個(gè)值,并打印出來(lái)。
This example program will output 2. This is because thedefault behavior of a signal that has a return type(float, the first template argument given to theboost::signal
class template) is to call all slots andthen return the result returned
by the last slot called. Thisbehavior is admittedly silly for this
example, because slots haveno side effects and the result is the last
slot connect.
該例程將輸出 2。這是因?yàn)榫哂蟹祷仡愋停?code class="computeroutput">float,即輸入 boost::signal類模板的第一個(gè)模板參數(shù))的信號(hào)的默認(rèn)行為是,調(diào)用所有的插槽,然后返回最后一個(gè)被調(diào)用插槽的結(jié)果。對(duì)本例來(lái)說(shuō),該行為確實(shí)有點(diǎn)傻,因?yàn)檫@些插槽沒有副作用并且結(jié)果就是最后的插槽連接。
A more interesting signal result would be the maximum of thevalues
returned by any slot. To do this, we create a customcombiner that looks
like this:
一個(gè)更有意思的信號(hào)結(jié)果是,求所有插槽返回值的最大值。為了做到這一點(diǎn),我們創(chuàng)建了一個(gè)自定義合并器,看起來(lái)像這樣:
template<typename T>
struct maximum
{
typedef T result_type;
template<typename InputIterator>
T operator()(InputIterator first, InputIterator last) const
{
// If there are no slots to call, just return the
// default-constructed value
if (first == last)
return T();
T max_value = *first++;
while (first != last) {
if (max_value < *first)
max_value = *first;
++first;
}
return max_value;
}
};
The maximum class template acts
as a functionobject. Its result type is given by its template
parameter, andthis is the type it expects to be computing the maximum
based on(e.g., maximum<float> would find the maximumfloat in a sequence of floats). When amaximum object is invoked, it is given an inputiterator sequence [first, last) that includes theresults of calling all of the slots. maximum uses thisinput iterator sequence to calculate the maximum element, andreturns that maximum value.
maximum 類模板就像一個(gè)函數(shù)對(duì)象。它的結(jié)果類型由其模板參數(shù)給出,并且它正是基于該類型計(jì)算最大值(例如,maximum<float>將在一系列 float中查找最大的 float)。當(dāng)調(diào)用maximum 對(duì)象時(shí),將給出一個(gè)輸入迭代器序列[first, last),其中包含了所有插槽調(diào)用的結(jié)果。maximum利用該輸入迭代器序列來(lái)計(jì)算最大元素,并返回那個(gè)最大值。
We actually use this new function object type by installing itas a
combiner for our signal. The combiner template argumentfollows the
signal's calling signature:
我們要把這個(gè)新的函數(shù)對(duì)象作為合并器安裝到我們的信號(hào),才能實(shí)際使用它。合并器模板參數(shù)跟在信號(hào)的調(diào)用簽名式之后。
Now we can connect slots that perform arithmetic functions anduse the signal:
現(xiàn)在我們可以連接執(zhí)行算術(shù)功能的插槽并使用信號(hào)了:
sig.connect("ient);
sig.connect(&product);
sig.connect(&sum);
sig.connect(&difference);
std::cout << sig(5, 3) << std::endl;
The output of this program will be 15,
becauseregardless of the order in which the slots are connected, the
productof 5 and 3 will be larger than the quotient, sum, ordifference.
該程序的輸出為 15,因?yàn)椴还懿宀鄣倪B接次序如何,5 和 3 的乘積將大于商、和,或差。
In other cases we might want to return all of the valuescomputed by
the slots together, in one large data structure. Thisis easily done
with a different combiner:
在其他情況下,我們可能要同時(shí)返回插槽計(jì)算的所有值,如保存在一個(gè)大型的數(shù)據(jù)結(jié)構(gòu)中。這可以用一個(gè)不同的合并器來(lái)輕松完成:
template<typename Container>
struct aggregate_values
{
typedef Container result_type;
template<typename InputIterator>
Container operator()(InputIterator first, InputIterator last) const
{
return Container(first, last);
}
};
Again, we can create a signal with this new combiner:
我們?cè)俅斡眠@個(gè)新的合并器創(chuàng)建信號(hào):
The output of this program will contain 15, 8, 1.6667, and 2. Itis interesting here thatthe first template argument for the signal class,float, is not actually the return type of the signal.Instead, it is the return type used by the connected slots and willalso be the value_type of the input iterators passedto the combiner. The combiner itself is a function object and itsresult_type member type becomes the return type of thesignal.
該程序的輸出將包含 15、8、1.6667,和 2。這里有趣的是,signal類的第一個(gè)模板參數(shù),float,竟然不是信號(hào)的返回類型。相反,該參數(shù)是所連接插槽的返回類型,并且它也是傳入合并器的輸入迭代器的value_type。合并器本身是個(gè)函數(shù)對(duì)象,并且它的result_type成員類型將成為信號(hào)的返回類型。
The input iterators passed to the combiner transform
dereferenceoperations into slot calls. Combiners therefore have the
option toinvoke only some slots until some particular criterion is met.
Forinstance, in a distributed computing system, the combiner may
askeach remote system whether it will handle the request. Only
oneremote system needs to handle a particular request, so after aremote
system accepts the work we do not want to ask any otherremote systems
to perform the same task. Such a combiner need onlycheck the value
returned when dereferencing the iterator, andreturn when the value is
acceptable. The following combiner returnsthe first non-NULL pointer to
a FulfilledRequest datastructure, without asking any later slots to fulfill therequest:
傳給合并器的輸入迭代器會(huì)將解引用操作轉(zhuǎn)換為插槽調(diào)用。因此合并器可選擇僅調(diào)用某些符合特定條件的插槽。例如,在分布計(jì)算系統(tǒng)中,合并器可能會(huì)詢問(wèn)
每個(gè)遠(yuǎn)程系統(tǒng)能否處理請(qǐng)求。對(duì)于一個(gè)特定請(qǐng)求,僅需一個(gè)遠(yuǎn)程系統(tǒng)進(jìn)行處理,因此當(dāng)一個(gè)遠(yuǎn)程系統(tǒng)接受該工作后,我們將不再要求任何其他遠(yuǎn)程系統(tǒng)來(lái)做同一個(gè)任
務(wù)。這樣一個(gè)合并器只需檢查迭代器解引用的返回值,并當(dāng)該值可以接受時(shí)就返回。以下的合并器返回第一個(gè)指向FulfilledRequest數(shù)據(jù)結(jié)構(gòu)的非空指針,而不必要求任何以后的插槽來(lái)完成請(qǐng)求:
struct DistributeRequest {
typedef FulfilledRequest* result_type;
template<typename InputIterator>
result_type operator()(InputIterator first, InputIterator last) const
{
while (first != last) {
if (result_type fulfilled = *first)
return fulfilled;
++first;
}
return 0;
}
};