`for_each_arg`的使用正确 - 转发过多? [英] Correct usage of `for_each_arg` - too much forwarding?

查看:182
本文介绍了`for_each_arg`的使用正确 - 转发过多?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我真的很高兴发现 for_each_arg(...) ,这使得处理参数包变得更容易。

I'm really happy to have discovered for_each_arg(...), which makes dealing with argument packs much easier.


template<class F, class...Ts>
F for_each_arg(F f, Ts&&...a) {
 return (void)initializer_list<int>{(ref(f)((Ts&&)a),0)...}, f;
}


其正确用法。有很多参数需要完美转发,但我执行任何不必要的转发吗?

I'm, however, confused on its correct usage. There are many arguments that need to be perfectly forwarded, but am I performing any unnecessary forwarding?

阅读代码变得越来越困难。

Reading the code becomes harder with excessive fowarding.

struct UselessContainer
{
    // Expects a perfectly-forwarded item to emplace
    template<typename T> void add(T&&) { }   
};

// Creates an `UselessContainer` already filled with `mArgs...`
auto makeUselessContainer(TArgs&&... mArgs)
{
    using namespace std;
    UselessContainer result;

    for_each_arg
    (
        [&result, &mArgs...] // Am I capturing the `mArgs...` pack correctly here?
        (auto&& mX) // Am I passing the arguments to the lambda correctly here?
        { 
            // Is this `forward` necessary?
            result.add(forward<decltype(mX)>(mX)); 

            // Could it be replaced with
            // `result.add(forward(mX));` 
            // ?             
        }, 
        forward<TArgs>(mArgs)... // I assume this `forward` is necessary.
    );

    return result;
}

我的所有问题/疑问都在上述代码示例的注释中表示。

All my questions/doubts are expressed in the comments in the above code example.

推荐答案

您的代码中的每个向前参数直到结束。右值引用的名称是左值,所以除非你每次传递参数,否则值类别信息将丢失。

也不可能调用向前没有显式的模板参数列表,因为模板参数只用在一个非推导的上下文中。实际上,没有显式参数列表的函数模板不能执行该作业。

Every forward in your code is indeed necessary to perfectly forward all arguments until the end. Names of rvalue references are lvalues, so unless you're forwarding everytime you pass arguments on, the value category information is lost.
Also it is impossible to call forward without an explicit template argument list as the template parameter is only used in one, non-deduced context. In fact, a function template called without an explicit argument list cannot do the job.

您可以尝试一个宏来缩短代码:

You can try a macro to somewhat shorten the code:

#define FORWARD(...) std::forward<decltype(__VA_ARGS__)>(__VA_ARGS__)

然后变成

for_each_arg
(
    // Removed superfluous capture
    [&result] (auto&& mX) { 
        result.add(FORWARD(mX));       
    }, 
    FORWARD(mArgs)...
);

也可以使用宏来代替 for_each_arg 首先:

It's also possible to use a macro instead of for_each_arg in the first place:

#define FOR_EACH_ARG(...) (void)std::initializer_list<int>{((__VA_ARGS__),0)...}

FOR_EACH_ARG( result.add(forward<TArgs>(mArgs)) );

这篇关于`for_each_arg`的使用正确 - 转发过多?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆