2016-07-26 13 views
0

テイク、例えば、次のコード:基本テンプレートパラメータなしでテンプレートテンプレートパラメータをテンプレートクラスに渡すにはどうすればよいですか?

// Say I have this class defined in some other file 
class Foo; 

// This class will act as a wrapper for an integer map 
// to function pointers, which will create type TFoo objects 
// depending on the given input (in this case a "const char*" 
template<class TFoo> 
struct Bar 
{ 
    typedef TFoo foo_t; 
    typedef TFoo (*get_foo_f_t)(const char*); 
    typedef std::unordered_map<int, get_foo_f_t> foo_handler_map_t; 

    Bar(const foo_handler_map_t& handlers) 
     : handlers_(handlers) 
    { 
    } 
    ~Bar() 
    { 
    } 

    const foo_handler_map_t& handlers_; 
}; 

// Now, this class will receive an _object_ of type 
// "const Bar<T>&", which will have an already initialized 
// map of integers to function pointers, different 
// functions will be called with different input values 
// via the public method, "action()". 
template<class TFoo, const Bar<TFoo>& CBar> 
class Quux 
{ 
    public: 
     Quux() 
      : bar_(CBar) 
     { 
     } 
     ~Quux() 
     { 
     } 

     TFoo action(int a, const char* x) 
     { 
      auto it = this->bar_.handlers_.find(a); 
      if (it == this->bar_.handlers_.end()) 
      { 
       // no handler defined for int `a' 
       return TFoo(); 
      } 
      // i.e. CBar.handlers_[a](x) 
      return it->second(x); 
     } 

    private: 
     const Bar<TFoo>& bar_; 
}; 


// Here is how the map of integers to function pointers 
// will be initialized... 
static std::unordered_map<int, Foo (*)(const char*)> handlers 
{ 
    { 0, _hdl_0 }, // _hdl_* functions defined in different file 
    { 1, _hdl_1 }, 
    { 2, _hdl_2 } 
}; 
// And then passed to a "const Bar<T>" type object here 
const Bar<Foo> bar (handlers); 


int main() 
{ 
    // --> HERE IS WHAT I WANT TO CHANGE <-- 
    Quux<decltype(bar)::foo_t, bar> quux; 
    // ------------------------------------- 

    // Example (trivial) use of the 'quux' object 
    std::cout << quux.action(0, "abc").baz() << std::endl; 
    std::cout << quux.action(1, "def").baz() << std::endl; 
    std::cout << quux.action(2, "ghi").baz() << std::endl; 

    return 0; 
} 

「Quux」クラスは2つのテンプレートパラメータ取ることに注意してください - また、「バー」クラスのテンプレートパラメータであるものを、としているテンプレートへの参照タイプconst Bar<T>のオブジェクトです。ここで、Tは 'Foo'に関連する任意のクラスです。

Quux<bar> quux; 

注:「バー」タイプBar<Foo>の目的であるが、また、任意のBar<T>型であることができるはず私は、次の代わりに行うことができるようにしたいと思います。

これは可能ですか?私は多分以下のようなものが迅速な回避策として使用することができると考えていたが、私は/* ??? */の場所に置くために何を把握することはできません:私は

template<const Bar</* ??? */>& CBar> 
using Nuff = Quux<decltype(CBar)::foo_t, CBar> 

Nuff<bar> nuff; 


EDIT

foo_handler_map_tオブジェクト全体のコピーを作成するのではなく、コピーが非効率的である(私は思う)ため、オブジェクトへの参照をテンプレートパラメータとして 'Quux'に渡します。私はいくつかの名前空間でグローバルに定義されているタイプconst Bar<T>のオブジェクトの束を持っている、などのように「Quux」オブジェクトを初期化できるようにすることができるようにしたい:

namespace blah 
{ 
std::unordered_map<int, /* funcptr type 0 */> _funcmap_0 { ... } 
std::unordered_map<int, /* funcptr type 1 */> _funcmap_1 { ... } 
... 

const Bar<Foo0> FSET0 (_funcmap_0); 
const Bar<Foo1> FSET1 (_funcmap_1); 
... 
} 

int main() 
{ 
    Quux<blah::FSET0> a; 
    Quux<blah::FSET1> b; 

    ... 

    return 0; 
} 

...そして私はしないでくださいそれをコンストラクタ引数として渡したい

+0

を' ?あなたがコンパイルしたことを示しているので、私はexternオブジェクトへのポインタのように有効だと思います。しかし、ここで目的は何ですか、達成しようとしているのは何ですか? –

+2

例をたくさん減らすことができればいいと思います。あなたの質問をキャッチするために必要な最小限のコードを入力してください! – Klaus

+2

これは現行のC++では不可能ですが、[n4469](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4469.html)が採用されると可能になります。 –

答えて

2

コメントは非常に便利です。

template<class TFoo> 
class Quux 
{ 
public: 
    Quux(const Bar<TFoo>& CBar) 
     : bar_(CBar) 
    {} 

    ~Quux() 
    {} 

    TFoo action(int a, const char* x) 
    { 
     auto it = this->bar_.handlers_.find(a); 
     if (it == this->bar_.handlers_.end()) 
     { 
     return TFoo(); 
     } 
     return it->second(x); 
    } 

private: 
    const Bar<TFoo>& bar_; 
}; 

をそしてQuuxのインスタンスを作成するための関数を定義します:あなたはテンプレート引数の数を減らすことを希望する場合は、あなたは、コンストラクタの引数としてCBarを渡すことができ

template <typename TFoo> 
auto make_Quux(const Bar<TFoo>& bar) 
{ 
    return Quux<TFoo>(bar); 
} 

その後main()に、あなたはmake_Quux()を使用することができます。この `テンプレート<クラスTFoo、constのバー &CBARを>何

int main() 
{ 
    auto quux = make_Quux(bar); 
    //... 
} 
+2

はい、私は誰かが参照のテンプレート引数を使用して、渡された各参照に対してまったく異なる型をインスタンス化する理由を見ません...しかし、あなたの例はクラスのセマンティクスを変更します。実際にOPが行っていることを反映するために、おそらくそれを編集する必要があります。つまり、最初のテンプレート引数とその上に描画するものを保持します。また、C++ 17では、コンストラクタがクラスのテンプレート引数を示すことができるようになる(関数が現在可能なので)、 'make_ *'関数は不要になることに注意してください。 –

関連する問題