簡體   English   中英

c++ 帶概念的參數包擴展

[英]c++ parameter pack expansion with concepts

如果取消注釋行 #1 和注釋行 #2,為什么會出現編譯錯誤? 演示: https://godbolt.org/z/KW6dhsrKd

#include <utility>

template <typename, std::size_t> concept prefix = true;

template<std::size_t>
struct dummy { template<typename T> constexpr dummy(T){}; };

template <auto N>
consteval auto nth_element(auto... args) 
{
return [&]<std::size_t... Is>(std::index_sequence<Is...>) {
    //return [](prefix<Is> auto..., auto arg, auto...) { //compile error // #1
    return [](dummy<Is> ..., auto arg, auto...) { // OK                  // #2
    return arg;
    }(args...);
}(std::make_index_sequence<N>());
}

int main()
{
    static_assert(nth_element<0>(1, 2, 3) == 1);
    static_assert(nth_element<1>(1, 2, 3) == 2);
    static_assert(nth_element<2>(1, 2, 3) == 3);
    
    return 0;
}

來自[dcl.fct]/22

一個縮寫的 function 模板等效於一個 function 模板 ([temp.fct]),其模板參數列表包含一個發明類型模板參數,用於 function 聲明的每個通用參數類型占位符,按出現順序排列。 [..] 如果相應的參數聲明聲明了 function 參數包,則發明的類型模板參數是模板參數包。

請注意, prefix<Is> auto...同時是包和包擴展。
所以轉換后的模板看起來像

[] <prefix<Is>... Args> (Args auto..., auto arg, auto...) {
    return arg;
}(args...)

這相當於

[] <typename... Args> requires(prefix<Args, Is> && ...) (Args..., auto arg, auto...) {
    return arg;
}(args...)

(這仍然會生成相同的錯誤消息。)
我們可以看到 1) Args處於非推導上下文中並且將始終保持為空,並且 2) IsArgs必須在長度上一致才能滿足約束條件。

評論中給出的解決方案不是理想的 IMO,因為創建元組可能相對昂貴(尤其是在編譯時)。 我認為你的解決方案+適當的轉發是目前最好的(直到我們得到適當的包下標)。 即是這樣的:

template<std::size_t>
struct dummy { constexpr dummy(auto&&){}; };

template <std::size_t N, typename... Args>
constexpr decltype(auto) nth_element(Args&&... args) {
    return [&]<std::size_t... Is>(std::index_sequence<Is...>) -> decltype(auto) {
        return [](dummy<Is> ..., auto&& arg, auto&&...) -> decltype(auto) { // OK                  // #2
            return std::forward<decltype(arg)>(arg);
        }(std::forward<Args>(args)...);
    }(std::make_index_sequence<N>());
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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