簡體   English   中英

擴展可變參數模板模板參數以用於例如 std::variant<T...>

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

這將是一個難以破解的難題。 我什至不知道這是否可能。

我的目標是創建一個接收函數,它偵聽多個隊列並將通過特定隊列(首先響應)接收到的對象粘貼到 return 語句中的堆棧。 這將通過 std::variant 完成。 棘手的地方是類型:每個隊列都有不同的類型,因此 multireceive() 中的變體需要從用於作為可變參數傳遞給它的隊列的模板參數構造。 當然最后隊列對象應該只作為引用傳遞。

到目前為止,這是我的方法,但您可以看到我非常不清楚如何編寫包擴展。 我想我可能會用這個來突破 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() {}

顯然,這甚至沒有遠程編譯,只是我試圖表明意圖。 隊列當然也只是一個存根。 Afaik 您甚至無法按名稱( T )獲取模板模板參數,這非常不幸。 有沒有比我聰明的人已經想出了如何解決這個問題?

注意

到目前為止,我這樣做的方式是通過非模板化 base_struct 上的動態調度。 但是,此解決方案會丟失類型信息,我的計划是通過 std::visit 在multireceive的調用點發送變體。 這將是一個非常巧妙的解決方案,可以直接從隊列事件中分派。

由於您的所有隊列都使用相同的模板( queue<...> ),因此您不需要模板模板參數(順便說一下,嵌套參數的名稱(在您的情況下為T )被忽略)。 你只需要一個類型包: typename ...T

我也擺脫了變量數組,而是選擇直接迭代參數,在折疊表達式中使用 lambda。 雖然這使得提取返回值變得更加困難,所以我將它放入了一個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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM