2011-04-11 6 views
0

オプションをお持ちの場合、どちらを選択しますか?デザイナーの視点から、実際に明らかにされていませんプログラミングテンプレートのスタイル

template<class CheckEveryNode<true>> 
struct X; 

or 

template<bool CheckEveryNode> 
struct X; 

、一方の側で、私たちは、実際のコードでは可読性があります。第二の側に

//taking first approach 
//somewhere in the code 
X<CheckEveryNode<false>> x; 

を入力すると、誰かが好むはるかがあります:

//taking second approach 
//somewhere in the code 
X<false> x;//but here we don't really see immediately what the false means. 

だから、あなたのご意見/ご提案

答えて

0

もみを楽しみにしてアプローチが面倒に見えます。私は、最初のものについて説得力のある理論的根拠がないときに、2番目のものに行くだろう。読みやすさに関しては、第2のものは読取り可能である。実際には、最初のものはホットチックの構文のために読みやすさを低下させます。

+0

@Nawazは複数の「ポリシー」があり、最初に選択した場合はX となることを覚えておいてください。より精巧だが非常に読みやすい。そして、古い格言は「コンピュータ・プログラムは数回だけコンピュータで読まれるが、数千ではないにしても何百人も読んでいる」と述べている。 –

+0

@何も私たちができることはありません:あなたはもっとわかりやすいものを教えてください: 'X ' OR 'X 、B_type 、C_type 、D_type 、E_type > '? – Nawaz

+0

@Nawazネーミングタイプの技術もあります。 –

0

私は第2のものも好きです。私の哲学は、なぜあなたがする必要がない場合は、余分なタイプを作成するだろうか?

1

まず

template<class CheckEveryNode<true>> 
struct X; 

は間違っているだろう、それは真か偽のどちらかの条件に特化するか、あなたが必要になり

template<template<bool> CheckEveryNode> 
struct X{}; 

次のようになります。

// above is true case, below is false case 
template<> 
struct X<CheckEveryNode<false> >{}; 

または部分的に使用します専門化は次のようになります。

template<class CheckEveryNode> 
struct X; 

template<bool B> 
struct X<CheckEveryNode<B> >{ 
    // real implementation 
}; 

これ以外にも、「期待どおり」であるため、2番目の実装は実装が簡単で読みやすくなります。テンプレート引数を指定すると、それが何であるかがわかります。余分な構造体は必要ありません。

2

多くの場合、メタプログラミングでおしゃべりをしていますが、「冗長」なアプローチしか勧められませんが、私が提案する最初のアプローチはあまり好きではありません。

ポリシーを使用する場合は、フラグを渡すだけでなく、独自の定義済み値に頼るのではなく、ポリシーオブジェクトを渡すことができます。例えば

struct NodeCheckerTag {}; 

struct CheckEveryNode { 
    typedef NodeCheckerTag PolicyTag; 
    void check(List const& list); 
}; 

struct CheckFirstNode { 
    typedef NodeCheckerTag PolicyTag; 
    void check(List const& list); 
}; 

template <typename Rand> 
struct CheckSomeNodes { 
    typedef NodeCheckerTag PolicyTag; 
    CheckSomeNodes(Rand rand): _rand(rand) {} 
    void check(List const& list); 
    Rand _rand; 
}; 

あなたのクラスは、このように、ユーザが選出するためにどのポリシーを選択できるようにする必要があります。

template <typename NodeChecker> 
class X: NodeChecker // allow stateful implementation but let EBO kick in 
{ 
}; 

PolicyTagは、複数のポリシーが存在するためである。

template <typename NodeChecker, typename NodeAllocator, typename NodeNotifier> 
class X; 

通常、わかりやすいデフォルトを設定する必要がありますが、常にその場合があります私はちょうど最後のカスタマイズしたい!あなたが唯一のいくつかの関数を呼び出すことを心配している場合、ポリシーから継承することで、選択は不要かもしれないと

template <typename Tag, typename Default, typename... Policies> 
struct PolicySelector 
{ 
    typedef /**/ type; 
}; 

template <typename... Policies> 
class X: Policies... 
{ 
    typedef typename PolicySelector<NodeCheckerTag, CheckNoNode, 
    Policies...>::type NodeCheckerPolicy; 
    typedef typename PolicySelector<NodeAllocatorTag, StdAllocator, 
    Policies...>::type NodeAllocatorPolicy; 
    ... 
}; 

注:は、可変長テンプレートに切り替えることにより、あなたはそれを得ることができます。派生クラス(ここではX)に明示的にtypedefする必要があるので、ポリシーに隠された内部typedefが必要な場合にのみ必要です。

+0

@Natthieuありがとうございます(具体的な例)。私がここで尋ねていたのは、書類を書くのが面倒かもしれないし、裸の「組み込みのもの」であっても、ポリシーによって、どちらをやるべきかということだけでした。他に何もない。しかし、あなたの(そのような精巧な)答えに感謝します。あなたの答えは –

1

複数のポリシーがあり、さまざまなブール値の意味がわからない場合は、ブール値をすべて削除してタグを使用できます。

struct CheckEvery { }; 
struct CheckNone { }; 

template<typename Check> struct Thingy; 
template<> Thingy<CheckEvery> { ... }; 
template<> Thingy<CheckNone> { ... }; 

または、ポリシーではなく、実行する作業を指定することができます。

struct CheckEvery { bool shouldCheck(int) { return true; } }; 
struct CheckNone { bool shouldCheck(int) { return false; } }; 
struct CheckOdds { bool shouldCheck(int i) { return i % 2; } }; 

template<typename Checker> struct Thingy { 
    Checker checker; 
    void someFunction(int i) { if(checker.shouldCheck(i)) check(i); } 
}; 

この例はうまく融合していませんが、あなたにはその考えがあります。たとえば、CheckerオブジェクトをThingyコンストラクタに提供したいとします。

+0

ありがとうございましたが、私はブール値の例をちょうど "例"として掲示しました。私はここで、ユーザーがどのようにポリシーを "裸の"タイプと見なしているのかについての意見について興味を持っています。 –

+0

あなたは提案を求めましたが、これは私のものです。 –