簡體   English   中英

對可變參數模板類型列表的每種類型進行操作的函數

[英]Function operating on each type of a variadic template typelist

我已經定義了一個這樣的類型列表:

template <typename ... Types> struct typelist {};

using my_list = typelist<int, double, bool, float>;

現在我有一個函數模板,例如

template<typename T>
void foo() {
    std::cout << typeid(T).name() << std::endl;
}

並想為類型列表中的每個類型調用它:

foo<int>();
foo<double>();
foo<bool>();
foo<float>();

我試圖找到一種遞歸方法來解決這個問題,但是我無法為所需的 foo 函數定義正確的、可能是嵌套的、可變參數模板。 你有什么關於這個問題的巧妙解決方案的提示嗎?

template<class... Types> auto foo_foreach(typelist<Types...>) {
     return (foo<Types>(), ...);
}

int main() {
    foo_foreach(my_list{});
}

對於真正的老派,使用您之前嘗試過的模板遞歸:

void foo_foreach(typelist<>) {}

template<class Head, class... Tail> void foo_foreach(typelist<Head, Tail...>);

template<class Head, class... Tail> void foo_foreach(typelist<Head, Tail...>) {
    foo<Head>();
    foo_foreach(typelist<Tail...>{});
}

這是一個僅使用 lambda 模板的c++20答案。

template <typename... Ts, typename C>
constexpr void for_types(C&& c) {
    (c.template operator()<Ts>(), ...);
}

for_types<int, float, char>([]<typename T>()
{
    std::cout << typeid(T).name() << std::endl;
});

如果您需要它與 C++14 一起使用,那么您可以使用initializer_list技巧來避免 C++17 折疊表達式。 這有望比遞歸方法更便宜:

template<class... Ts> void foo_foreach(typelist<Ts...>) {
    (void) std::initializer_list<int>{(foo<Ts>(), 0)...};
}

int main() {
    foo_foreach(my_list{});
}

Godbolt 示例: https ://godbolt.org/z/o91Th466s

https://blog.tartanllama.xyz/exploding-tuples-fold-expressions/ 上有關於initializer_list技巧的很好解釋

從那篇文章:

[...] 參數包只能在需要語法列表的上下文中擴展,例如初始化程序和函數調用參數。 你不能只是在函數體中裸露它們。 在 C++17 中,這個問題有一個很好的解決方案,但在此之前我們需要使用一些非常可怕的技巧。 [...] 一種可能性 [...] 使用std::initializer_list創建一個可以擴展參數包的上下文。

訣竅是, 0initializer_list程序中,它評估函數調用,並使用 0 作為初始化程序值。

暫無
暫無

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

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