2016-12-07 119 views
2

我很難理解爲什麼下面的簡單程序不能編譯。我有一個variadic模板類(下面的my_type),我想用它來轉換一個mpl向量。下面的代碼片段導致編譯錯誤「/ boost/mpl /aux_/preprocessed/gcc/apply_wrap.hpp:38:19:'apply'在'template'關鍵字之後沒有引用模板。使用boost mpl lambda與variadic模板類

#include <boost/mpl/vector.hpp> 
#include <boost/mpl/transform.hpp> 

template <class... T> 
struct my_type{}; 

using namespace boost::mpl; 

using test_type = vector<int, double>; 

// expected result is vector< my_type<int>, my_type<double> > 
using result_type = transform< test_type, my_type<_> >::type; 

int main() { 

} 

製作my_type採取一個模板參數正常,但我想明白爲什麼一個可變版本不起作用。先謝謝你!

回答

0

變換所期望的第二個參數是一個未經過的一元操作。

在你的情況下,my_type不是metafunction mpl預計,因爲它正在使用可變參數列表。

A metafunction在最簡單的情況下暴露了type typedef或ststic boolvalue。對於如:

template <typename T> 
struct add_pointer { 
    using type = T*; 
}; 

注意如何add_pointer轉換所提供的模板參數。這是unary操作的一個示例,因爲它只需要一個模板參數T

在您的例子my_type純粹是一個類型,並且不能被用作元函數或操作所要求的transform元函數,其是具有type字段,用於指示變換的類型它不滿足metafunction的標準。

在某些情況下,如下面的Detailed Reasoning部分所述,將簡單電路板類型轉換爲metafunction

文檔參考:http://www.boost.org/doc/libs/1_31_0/libs/mpl/doc/ref/Reference/transform.html

代碼:

#include <boost/mpl/vector.hpp> 
#include <boost/mpl/transform.hpp> 
#include <boost/mpl/equal.hpp> 

#include <type_traits> 
#include <typeindex> 
#include <iostream> 

template <class... T> 
struct my_type{}; 

using namespace boost::mpl; 

using test_type = vector<int, double>; 

template <typename T> 
struct add_my_type { 
    using type = my_type<T>; 
}; 

using result_type = typename transform< test_type, add_my_type<_1> >::type; 

int main() { 
    static_assert (equal<result_type, vector< my_type<int>, my_type<double> >>::value, "Nope!!"); 

    std::cout << typeid(result_type).name() << std::endl; 
} 

LIVE DEMO

詳細原因

上面的原因解釋是相當短暫的,應該足以回答這個問題。但我們儘可能多地挖掘細節。

免責聲明:我不是boost :: mpl的專家。

template <class T> 
struct my_type{}; 

但是,這並不與我前面提到的即operation需要type標識符順利:

按照下面的評論由OP,如果我們改變my_type原來的代碼工作。所以,讓我們看看,什麼MPL與引擎蓋下做:

struct transform有點樣子:

template< 
    typename Seq1 = mpl::na 
, typename Seq2OrOperation = mpl::na  
, typename OperationOrInserter = mpl::na   
, typename Inserter = mpl::na    
> 
struct transform { 
    boost::mpl::eval_if< 
     boost::mpl::or_< 
      boost::mpl::is_na<OperationOrInserter>, 
      boost::mpl::is_lambda_expression<my_type<mpl_::arg<1> > >, 
      boost::mpl::not_<boost::mpl::is_sequence<my_type<mpl_::arg<1> > > >, 
      mpl_::bool_<false>, 
      mpl_::bool_<false> 
     >, 
     boost::mpl::transform1< 
      boost::mpl::vector<int, double>, 
      my_type<mpl_::arg<1>>, 
      mpl_::na 
     >, 
     boost::mpl::transform2<boost::mpl::vector<int, double>, 
      my_type<mpl_::arg<1> >, 
      mpl_::na, mpl_::na> 
     > 

}; 

查看這裏的重要組成部分,是is_lambda_expression元函數基本上檢查,如果你Operation滿足的要求metafunction

運用一些重宏觀和模板機械和專業後,上述檢查synthesises以下結構:

template< 
     typename IsLE, typename Tag 
    , template< typename P1 > class F 
    , typename L1 
    > 
struct le_result1 
{ 
    typedef F< 
      typename L1::type 
     > result_; 

    typedef result_ type; 
}; 

這裏,F是你my_typeL1placeholder。所以,從本質上講,上面的結構只不過是我在最初的回覆中已經顯示的add_my_type

如果我到現在爲止是正確的,le_result1operation將在您的sequence執行。

+1

謝謝你的幫助。我的印象是'my_type <_1>'本質上是通過mpl :: lambda轉換成一元函數類的。我還不是很清楚,爲什麼不是這樣,因爲一個參數傳遞給'my_type'。你能解釋一下爲什麼'my_type <_1>'不被認爲是一個有效的一元元函數類嗎? – linuxfever

+0

已更新我的答案。希望現在應該清楚。 – Arunmu

+1

恐怕我不同意「根據轉換元函數的要求,它有一個類型字段來表示轉換後的類型」。例如,如果將'my_type'更改爲'template struct my_type {}',則代碼將編譯並提供所需的輸出,即使'my_type'仍不會顯示'type'字段。 – linuxfever