[英]Compile-time recursion with SFINAE as template argument
我在玩模板,我想用它們來編寫一個將在編譯時評估的遞歸函數。 我希望它根據我傳遞給它的數字進行分支。 該函數確實有一個約束; 我想保留返回值。
所以這是我嘗試編寫函數(它不編譯):
template<int n, typename std::enable_if_t<n==1>>
constexpr auto fun() { return std::make_tuple(1); }
template<int n, typename std::enable_if_t<n==2>>
constexpr auto fun() { return std::make_tuple(fun<1>(), 2); }
template<int n, typename enable = void>
constexpr auto fun() {
return std::tuple_cat(fun<n-1>(), n);
}
int main() {
constexpr auto x = fun<4>();
return 0;
}
我面臨的問題是我不確定將std::enable_if_t
語句放在哪里,以及如何准確地編寫它以確保我的函數正確分支。 我在這里缺少什么?
假設您想連接元組並以以下形式創建它
fun<4>() == tuple(1, 2, 3, 4);
你可以寫兩個模板,比如
template<int n, std::enable_if_t<n == 1>* = nullptr>
constexpr auto fun()
{
return std::make_tuple(1);
}
template<int n, std::enable_if_t<n != 1>* = nullptr>
constexpr auto fun()
{
return std::tuple_cat(fun<n-1>(), std::tuple(n));
}
但是,這不是執行此操作的“C++17 方式” 。 使用if constexpr
可以更好地表達它
template<int n>
constexpr auto fun2()
{
if constexpr (n > 1)
return std::tuple_cat(fun2<n-1>(), std::tuple(n));
else
return std::tuple(1);
}
關於序列創建(例如1, 2, 3, 4, ...
)還有std::integer_sequence
可以與模板參數包結合使用
template <int... nums>
constexpr auto construct(std::integer_sequence<int, nums...>)
{
return std::tuple((nums + 1)...);
}
template<int n>
constexpr auto fun3()
{
return construct(std::make_integer_sequence<int, n>());
}
這是一個完整的例子。
我不清楚你到底想要什么但是......讓我猜猜:你想要的東西如下
#include <tuple>
#include <type_traits>
template<int n, std::enable_if_t<n==1, bool> = true>
constexpr auto fun() { return std::make_tuple(1); }
template<int n, std::enable_if_t<n!=1, bool> = true>
constexpr auto fun() { return std::tuple_cat(fun<n-1>(), std::make_tuple(n)); }
int main() { constexpr auto x = fun<4>(); }
訣竅
template<int n, typename enable = void>
是模板類的 SFINAE 技巧,其中有主要版本和一些專業化; 所以主版本定義了通過std::enable_if
啟用/禁用 SFINAE 的簽名和專業化。
使用函數,您可以重載函數,但不能進行部分專業化。 您必須單獨啟用/禁用每個重載功能
template<int n, std::enable_if_t<n==1, bool> = true>
// ...
template<int n, std::enable_if_t<n!=1, bool> = true>
// ...
注意我寫的
template<int n, std::enable_if_t<n==1, bool> = true>
並不是
template<int n, typename = std::enable_if_t<n==1>>
第二種形式也可用於啟用/禁用單個功能,但當您具有具有相同簽名的不同功能(如您的情況)並且您只想啟用一個版本時,則不起作用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.