2017-07-17 123 views
1

我以前問一個問題關於創建編譯時列表數據結構,並建議使用Boost.hana如何使用Boost hana遞歸創建一個constexpr列表?

我想這個基本的測試代碼:

#include <boost/hana/tuple.hpp> 
#include <boost/hana/for_each.hpp> 
#include <boost/hana/concat.hpp> 
#include <iostream> 

namespace hana = boost::hana; 

template<typename A, typename R> 
constexpr R parse(A count) 
{ 
    if(count == 0) 
    { 
    return hana::make_tuple(0); 
    } 
    else 
    { 
    return parse(count - 1); 
    } 
} 


int main() 
{ 
    constexpr auto l = parse(10); 

    hana::for_each 
    (
    l, 
    [](auto const& element) 
    { 
     std::cout << element << std::endl; 
    } 
); 

} 

但是,模板類型扣不工作,因爲遞歸函數的每次調用都返回一個不同的類型。 有沒有辦法解決這個問題?

回答

2

當你用hana進行元編程時,你必須瞭解的主要事情是沒有值 - 我們不是操縱數字之類的東西,而是操縱類型。這些類型可能具有與它們相關的值,但它們仍然是類型。這個術語是IntegralConstant

你想要的是一樣的東西:

template <class C> 
constexpr auto parse(C count) 
{ 
    if constexpr(count == 0_c) { 
     return hana::tuple(count); 
    } else { 
     return hana::flatten(hana::make_tuple(
      hana::tuple(count), 
      parse(count - 1_c))); 
    } 
} 

constexpr auto l = parse(10_c); 

10_c是IntegralConstant其值是10的一個實例。我們可以在基本情況下將其與0_c進行比較。這看起來像價值平等,這是關於使用Hana的真正好處,但它不是價值平等 - 它純粹是基於類型的。

parse(10_c)的結果是<10,9,8,7,6,5,4,3,2,1,0>的編譯時元組等效值。


需要注意的是這樣的:

template<typename A, typename R> 
constexpr R parse(A count); 

不是一個特別有用的功能模板,因爲R是一種非推斷上下文,因此必須在調用點指定。無論parse()的身體如何,parse(10)都不合格。