2016-12-07 2 views
2

다음 간단한 프로그램이 컴파일되지 않는 이유를 이해하는 데 어려움을 겪고 있습니다. 내가 variplic 템플릿 클래스 (my_type 아래) mpl 벡터를 변환하는 데 사용하고 싶습니다. 다음 스 니펫은 컴파일 오류 "/ template/template/template"키워드 다음에 'apply'가 템플릿을 참조하지 않는 "/boost/mpl/aux_/preprocessed/gcc/apply_wrap.hpp:38:19 오류를 발생시킵니다. 만들기 my_typevariadic 템플릿 클래스로 boost mpl lambda 사용

#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() { 

} 

는 하나의 템플릿 매개 변수가 잘 작동 가지고,하지만 난 가변 버전이 작동하지 않는 이유를 이해하고 싶습니다. 미리 감사드립니다.

답변

0

변환에 의해 예상되는 두 번째 인수는 전달하지 않는 단항 연산입니다.

my_type은 variadic 매개 변수 목록을 사용하기 때문에 mpl이 예상하는 metafunction이 아닙니다.

간단한 경우의 metafunctiontype 타입 정의 또는 ststic boolvalue을 노출시킨다. 예 :

제공된 템플릿 매개 변수를 변환하는 방법은 add_pointer입니다. 이는 하나의 템플릿 매개 변수 T 만 사용하기 때문에 unary 연산의 예입니다. 하여 예 my_type에서

순수 형태이며, 변환 유형을 표시하는 type 필드가있는 transform metafunction 의해 요구가 metafunction의 기준을 만족하지 않는 등의 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{}; 

하지만 그건 내가 즉이 operationtype 식별자를 필요로 앞서 언급 한 것과 잘되지 않습니다 우리가 my_type을 변경하는 경우

는 OP 아래의 코멘트 당으로, 원래의 코드가 작동합니다.

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> 
     > 

}; 

이쪽을 봐해야 할 중요한 부분은 기본적 Operation가의 요구 사항을 충족하는지 확인하는 is_lambda_expression metafunction입니다 :

struct transform 다소 같습니다 : 그래서, MPL은 후드 아래에 무엇을하는지, 볼 수 있습니다 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; 
}; 

, Fmy_type하고 L1placeholder입니다. 따라서 본질적으로 위의 구조체는 초기 응답에서 보여준 add_my_type뿐입니다.

지금까지 올바르다면, 에서 수행 할 operationle_result1입니다.

+1

감사합니다. 필자는'my_type <_1>'가 나중에 mpl :: lambda를 통해 단항 메타 클래스로 변형된다는 인상을 받았다. 왜 하나의 인수가'my_type'에 전달 되었기 때문에 그 이유가 무엇인지 아직 명확하지 않습니다. 왜'my_type <_1>'이 유효한 단일 메타 함수 클래스로 간주되지 않는지 좀 더 설명해 주시겠습니까? – linuxfever

+0

내 대답이 업데이트되었습니다. 잘하면 지금은 분명해야합니다. – Arunmu

+1

"변환 된 형식을 나타내는 형식 필드가있는 변환 메타 함수에서 요구하는대로"나는 동의하지 않습니다. 예를 들어'my_type'을' struct my_type {}'으로 변경하면,'my_type'이 여전히'type' 필드를 노출하지 않더라도, 코드는 컴파일하고 원하는 결과를 제공합니다. – linuxfever

관련 문제