简体   繁体   English

扩展可变参数模板模板参数以用于例如 std::variant<T...>

[英]Expand variadic template template parameters for use in e.g. std::variant<T...>

This will be a hard nut to crack.这将是一个难以破解的难题。 I don't even know if it's possible.我什至不知道这是否可能。

My goal is to create a receive function that listens to multiple queues and pastes the object received via the particular queue (that responds first) to the stack in the return statement.我的目标是创建一个接收函数,它侦听多个队列并将通过特定队列(首先响应)接收到的对象粘贴到 return 语句中的堆栈。 This will be done via std::variant.这将通过 std::variant 完成。 The tricky bits are types: Every queue holds different types, so the variant inside multireceive() needs to be constructed from the template parameters used for the queues passed into it as varargs.棘手的地方是类型:每个队列都有不同的类型,因此 multireceive() 中的变体需要从用于作为可变参数传递给它的队列的模板参数构造。 Of course in the end the queue objects should only be passed as references.当然最后队列对象应该只作为引用传递。

Here's my approach so far, but you can see I'm very unclear about how to write the pack expansions.到目前为止,这是我的方法,但您可以看到我非常不清楚如何编写包扩展。 I think I'm probably scratching the limits of C++ with this:我想我可能会用这个来突破 C++ 的限制:

#include <array>
#include <variant>

template <typename T>
struct queue
{
    T queue_[100];
    
    T receive()
    {
        return queue_[0];
    }
};

// doesn't compile!
template <template <typename... T> class Q>
std::variant<T...> multireceive(Q<T>&... Arg)
{
    std::array<std::variant<Arg*...>, sizeof...(T)> queues = { (&Arg )... };

    do {
        for (size_t i=0; i < sizeof...(T); ++i) {
            if (queues[i]->receive()) {
                return *queues[i];
            }
        }
    } while(1) // busy wait
}

int main() {}

Clearly this doesn't even remotely compile, its just me trying to show intent.显然,这甚至没有远程编译,只是我试图表明意图。 The queue is of course also just a stub.队列当然也只是一个存根。 Afaik you can't even grab the template template parameter by name ( T ) which is very unfortunate. Afaik 您甚至无法按名称( T )获取模板模板参数,这非常不幸。 Has someone smarter than me already figure out how to solve that problem?有没有比我聪明的人已经想出了如何解决这个问题?

Note :注意

The way I did it until now is via dynamic dispatch over a non-templated base_struct.到目前为止,我这样做的方式是通过非模板化 base_struct 上的动态调度。 This solution however loses type information and my plan is to dispatch the variant via std::visit at the callsite of multireceive .但是,此解决方案会丢失类型信息,我的计划是通过 std::visit 在multireceive的调用点发送变体。 This would then be a very neat solutions to dispatch directly from queue events.这将是一个非常巧妙的解决方案,可以直接从队列事件中分派。

Since all your queues use the same template ( queue<...> ), you don't need a template template parameter (in which, by the way, the name of the nested parameter ( T in your case) is ignored).由于您的所有队列都使用相同的模板( queue<...> ),因此您不需要模板模板参数(顺便说一下,嵌套参数的名称(在您的情况下为T )被忽略)。 You just need a type pack: typename ...T .你只需要一个类型包: typename ...T

I also got rid of the variant array, and instead opted to iterate over the arguments directly, using a lambda in a fold expression.我也摆脱了变量数组,而是选择直接迭代参数,在折叠表达式中使用 lambda。 Though this makes extracting the return value harder, so I've put it into an optional :虽然这使得提取返回值变得更加困难,所以我将它放入了一个optional的:

#include <array>
#include <optional>
#include <variant>

template <typename T>
struct queue
{
    T queue_[100];
    
    T receive()
    {
        return queue_[0];
    }
};

template <typename ...P>
std::variant<P...> multireceive(queue<P> &... args)
{
    std::optional<std::variant<P...>> ret;

    while (true)
    {
        // For each `args...`:
        ([&]{
            // Do something with `args` (the current queue).
            if (args.receive())
            {
                ret.emplace(args.queue_[0]);
                return true; // Stop looping over queues.
            }
            return false;
        }() || ...);

        if (ret)
            break;
    }

    return *ret;
}

int main()
{
    queue<int> a;
    queue<float> b;

    std::variant<int, float> var = multireceive(a, b);
}

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

相关问题 为什么不能使用auto作为模板类型参数(例如std :: array <auto, 5> )? - Why can't you use auto as a template type argument (e.g. std::array<auto, 5>)? 无法将std :: bind与可变参数模板参数一起使用 - Unable to use std::bind with variadic template parameters 变量模板作为std :: function的参数 - Variadic template as parameters to std::function 如何提取/扩展可变参数模板参数 - How to extract/expand variadic template parameters c++ 使用 std::enable_if 有条件地将 getter 添加到可变参数变体模板 - c++ Use std::enable_if to conditionally add getters to a variadic variant template Variadic可变参数模板模板参数 - Variadic variadic template template parameters 标准中的哪里是模板参数的语法,例如,`std::function<int(char)> `定义?</int(char)> - Where in the standard is the grammar for the template argument in, e.g., `std::function<int(char)>` defined? 模板 arguments 中的括号,例如 std::function<int(int, float)></int(int,> - Parentheses inside template arguments e.g. std::function<int(int, float)> 将std :: function与lambda和variadic模板一起使用 - Use std::function with lambda and variadic template 如何使用variadic模板使用std :: function - How to use std::function using variadic template
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM