2010-05-25 119 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)。

應該可以使您的設計適應這種技術。當然,一旦您引入了具有隱藏默認值的額外模板參數,您需要選擇覆蓋使用您的策略類的代碼的情況。這與使用多種特質將專門行爲與客戶端代碼進行通信時沒有什麼不同,除了策略將所有內容都很好地包裝在一起。