경고 : 문제를 설명하는 데 필요한 사전 지식이 필요합니다. 첫째 Vandevoorde 및 Josuttis에의 채널 16.1에서 설명하는 명명 된 템플릿 인수 관용구 편리하게 Boost.Parameter 라이브러리 위의 코드는 이름으로 arbritrary 위해 BreadSlicer
의 선택 템플릿 매개 변수를 대체 할 수Boost.Parameter : CRTP와 조합 된 명명 된 템플릿 인수
#include <iostream>
#include <typeinfo>
#include <boost/parameter.hpp>
#include <boost/static_assert.hpp>
struct DefaultPolicy1 {};
struct DefaultPolicy2 {};
typedef boost::parameter::void_ DefaultSetter;
BOOST_PARAMETER_TEMPLATE_KEYWORD(Policy1_is)
BOOST_PARAMETER_TEMPLATE_KEYWORD(Policy2_is)
typedef boost::parameter::parameters<
boost::parameter::optional<tag::Policy1_is>,
boost::parameter::optional<tag::Policy2_is>
> PolicySelector;
template
<
class PolicySetter1 = DefaultSetter,
class PolicySetter2 = DefaultSetter
>
class BreadSlicer
{
typedef typename PolicySelector::bind<
PolicySetter1,
PolicySetter2
>::type Policies;
public:
// extract policies:
typedef typename boost::parameter::value_type<
Policies, tag::Policy1_is, DefaultPolicy1
>::type P1;
typedef typename boost::parameter::value_type<
Policies, tag::Policy2_is, DefaultPolicy2
>::type P2;
};
작성 할 수 있습니다 그들 Policy1_is
및 Policy2_is
. 따라서 많은 기본 매개 변수가있는 정책 기반 설계가 매우 편리합니다. 정책 기반의 디자인과 매우 미묘한 ODR 위반 (에 대한 설명 Alexandrescu에 의해이 오래된 post 참조) 피하기 위해
int main()
{
typedef BreadSlicer<> B1;
// can override any default policy
typedef BreadSlicer< Policy1_is<int> > B2;
typedef BreadSlicer< Policy2_is<char> > B3;
// order of policy-setting is irrelevant
typedef BreadSlicer< Policy1_is<int>, Policy2_is<char> > B4;
typedef BreadSlicer< Policy2_is<char>, Policy1_is<int> > B5;
// similar static asserts work for B1 ... B4
BOOST_STATIC_ASSERT((std::is_same<B5::P1, int >::value));
BOOST_STATIC_ASSERT((std::is_same<B5::P2, char>::value));
return 0;
}
, 나는 명명 된 템플릿 인수에 CRTP 패턴을 적용 할 수 있도록하고 싶습니다 :
를int main()
{
// ERROR: this code does NOT compile!
struct CuriousBreadSlicer
:
BreadSlicer< Policy1_is<CuriousBreadSlicer> >
{};
typedef CuriousBreadSlicer B6;
BOOST_STATIC_ASSERT((std::is_same<B6::P1, CuriousBreadSlicer>::value));
BOOST_STATIC_ASSERT((std::is_same<B6::P2, DefaultPolicy2 >::value));
return 0;
}
그러나, Boost.Parameter 구현은 위의 일부 내부 static_assert는 (VC10 SP1)과 같은 메시지
의 주요 실패 때문에 컴파일에 실패 :: CuriousBre을 adSlicer이 정적 검사가 해제 할 수 있습니다 :
이 질문 '__is_base_of'정의되지 않은 클래스는 고유 유형의 특성을 컴파일러하는 인수로 사용할 수 없습니다 '? 매크로 또는 템플릿 트릭을 통해? 가능한 워크 어라운드에 관해서
:
- 위 코드 this handwritten code 기능적으로 동일하다. 이 코드에서는 CRTP 패턴이 작동합니다. 그러나 은 Boost.Parameter 라이브러리가 매우 편리하므로 많은 보일러 플레이트 코드가 필요합니다. 은 자동화합니다.
- 템플릿의 목록에서 항상 CRTP 매개 변수를 먼저 요구하고
Policy1_is
클래스로 래핑하지 않아도됩니다. 이렇게하면 컴파일 시간 오류가 해결되지만 재정의의 순서 독립성이 손실됩니다.
그래서 저는 골프 선수들이 "클럽간에"부르는 것 같아요. 어떤 솔루션이 가장 좋을까요?
CRTP는 유형 특성에서 오는 ODR을 피하기 위해 사용됩니다. 내 질문에 링크 Alexandrescu에 의해 게시물을 참조하십시오. 본질적으로 정책 클래스는 모든 특수 특성을 표시 할 때 사용됩니다. 포장 아이디어가 좋습니다. 이상적으로는'boost :: parameter :: value_type '에 전달되는'false'가 기본값 인 추가 매개 변수가되어야합니다. –
TemplateRex
명명 된 템플릿 인수는 매우 필수적인 것 같습니다 효과적인 정책 기반 프로그래밍 왜 그들이 표준에 포함시키지 않았습니까? – AlwaysLearning