2010-05-25 120 views
4

很难想出一个好标题的这个问题。我真正需要的是能够使用不同数量的参数提供模板参数来代替单个参数。不会使一个很大的意义,所以我就去了原因:政策设计,默认

template < typename T, template <typename,typename> class Policy = default_policy > 
struct policy_based : Policy<T, policy_based<T,Policy> > 
{ 
    // inherits R Policy::fun(arg0, arg1, arg2,...,argn) 
}; 

// normal use: 
policy_base<type_a> instance; 

// abnormal use: 
template < typename PolicyBased > // No T since T is always the same when you use this 
struct custom_policy {}; 

policy_base<type_b,custom_policy> instance; 

这笔交易,对于许多不正常的使用策略将基于一个单一类型的T,并不能真正参数化在T上,所以将T作为参数是没有意义的。对于其他用途,包括默认情况下,政策是有意义的任何T.

我有几个想法,但他们都不是真正的最爱。我认为我有一个更好的答案 - 使用组合而不是策略 - 但后来我意识到我有这种情况,fun()实际上需要额外的信息,类本身不会有。

这是像我重构这个愚蠢的结构,我已经得到了它不少定制版本的周围,我试图巩固第三次。我希望这次得到一些东西,而不是仅仅在周围钓鱼,希望这次有用。所以我现在只是在寻找想法,希望有人有些事情会让我印象深刻,因为我会改变神性。任何人都有一个好主意?

编辑:您可能会问自己,为什么我不只是基于模板的default_policy策略的定义检索吨。原因是default_policy实际上是专门为某些类型T设计的。既然问了这个问题,我已经提出了一些可能是我需要的东西,随后会发生,但我仍然可以使用其他一些想法。

template < typename T > 
struct default_policy; 

template < typename T, template <typename> class Policy = default_policy > 
struct test : Policy<test<T,Policy>> 
{}; 


template < typename T > 
struct default_policy< test<T, default_policy> > 
{ 
    void f() {} 
}; 

template < > 
struct default_policy< test<int, default_policy> > 
{ 
    void f(int) {} 
}; 

编辑: 仍然搞乱它。我不喜欢上面的内容,因为它使得default_policy与“test”永久耦合,所以不能在其他方法中重用,比如下面提出的多模板。它也不会扩展,至少需要“测试”参数列表。尝试失败,直到我发现了另一个似乎工作至今的几个不同的方法:

template < typename T > 
struct default_policy; 

template < typename T, template <typename> class Policy = default_policy > 
struct test : Policy<test<T,Policy>> 
{}; 

template < typename PolicyBased > 
struct fetch_t; 

template < typename PolicyBased, typename T > struct default_policy_base; 

template < typename PolicyBased > 
struct default_policy : default_policy_base<PolicyBased, typename fetch_t<PolicyBased>::type> {}; 

template < typename T, template <typename> class Policy > 
struct fetch_t< test<T,Policy> > { typedef T type; }; 

template < typename PolicyBased, typename T > 
struct default_policy_base 
{ 
    void f() {} 
}; 

template < typename PolicyBased > 
struct default_policy_base<PolicyBased,int> 
{ 
    void f(int) {} 
}; 

回答

1

我有一个类似的问题,并没有找到一个理想的答案。据我所知,C++没有对变量的模板参数的优雅支持,所以你必须通过在另一个类中“包装”额外的参数来解决它。

policy_base< twoArgs<part1, part2> > 

你几乎可以此一点点通过将制作的typedef为twoArgs,但不是很多在这个基本情况。 (请记住,您可以通过模板类使用成员类型定义“做”模板类型定义)。

或具有核心模板的许多不同的声明,用不同的ARGS;

template< typename T1 > struct base {...} 
template< typename T1, typename t2 > struct base {...} 
//etc 
+0

最初我不喜欢多重声明的想法,因为这样做的目的是整合许多相似但略有不同的对象来共享代码。尽管大部分复制/粘贴的东西都可以被拉下,但是有适当的基本分类;我不得不比最初预期的要多得多,但是... ...这个twoArgs的想法也很有趣,如果考虑命名参数,这个想法可能会更有用。谢谢。 +1 – 2010-05-25 22:01:14

1

你看过所谓的命名模板参数吗?这允许你有许多隐藏的默认参数,每个参数都可以被名称覆盖(即以任意顺序)。这是一种依赖多层次间接和多重继承的技巧。它在Vandevoorde & Josuttis的书“模板完全指南”的第16.1章中描述。对于在线博览会,请参阅here。这个想法实施于Boost.Parameter

下面是该Boost.Parameter库的简短总结。

步骤1)您通过parN通过下面的宏声明每个参数par0

BOOST_PARAMETER_TEMPLATE_KEYWORD(par0) 
BOOST_PARAMETER_TEMPLATE_KEYWORD(par1) 
// ... 
BOOST_PARAMETER_TEMPLATE_KEYWORD(parN)  

每个宏将定义命名空间tag两个普通班par0和命名空间范围类模板par0

namespace tag { struct par0; } // keyword tag type 
template <class T> 
struct par0 
: 
    parameter::template_keyword<tag::par0, T> 
{}; 

步骤2) y OU声明了必需和可选参数类签名:

using boost::mpl::_; 

typedef parameter::parameters< 
    parameter::required<tag::par0> 
    , parameter::optional<tag::par1> 
    // ... 
    , parameter::optional<tag::parN> 
> your_signature; 

步骤3)你宣布你的策略类

template < 
    class a0 
    , class a1 = parameter::void_ 
    // ... 
    , class aN = parameter::void_ 
> 
struct your_policy 
{ 
    // Create ArgumentPack 
    typedef typename 
     your_signature::bind<a0, a1, /* ... */ ,aN>::type 
    args; 

    typedef typename parameter::value_type< 
     args, tag::par0>::type par0; 

    typedef typename parameter::value_type< 
     args, tag::par1, your_par1_default>::type par1; 

    // ... 

    typedef typename parameter::value_type< 
     args, tag::parN, your_parN_default>::type parN; 
}; 

步骤4)定义你的政策和专业

template<typename T> 
class default_policy 
: 
    your_policy<T> // all hidden template parameters equal to their defaults 
{}; 

template<typename T> 
class some_par2_specialized_policy 
: 
    your_policy<T, par2<some_override_for_par2> > // note par1 does not have to be overriden!! 
{}; 

对于灵活且可扩展的基于策略的设计,我的经验是,Boost.Pa rameter就像一个魅力一样(如果你有超过8个隐藏参数,你可能需要重写BOOST_PARAMETER_MAX_ARITY)。

应该可以使您的设计适应这种技术。当然,一旦您引入了具有隐藏默认值的额外模板参数,您需要选择覆盖使用您的策略类的代码的情况。这与使用多种特质将专门行为与客户端代码进行通信时没有什么不同,除了策略将所有内容都很好地包装在一起。