2016-07-26 164 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」類需要兩個模板參數 - 一個是也爲「酒吧」類的模板的參數,以及一個模板的引用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; 


編輯

我因爲複製效率不高(我認爲),而不是製作整個對象的副本,所以將對象的引用傳遞給'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

這是什麼'模板<類TFoo,常量酒吧&C杆>' ?既然你指出它編譯,我猜它是有效的,就像一個指向某個外部對象的指針。但是,這裏的目的是什麼,你想達到什麼目的? –

+2

如果你可以減少你的例子,這將是很好的。請提供我們需要的最低限度的代碼來解決您的問題! – Klaus

+2

這在目前的C++中是不可能的,只要採用[n4469](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4469.html)就可以實現。 –

回答

2

評論是非常有用的。但是,如果你想減少模板參數的個數,可以通過CBar作爲參數的構造器:

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一個實例:

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

然後在main(),你可以使用make_Quux()

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

是的,我不明白爲什麼有人會爲引用使用模板參數,因此爲每個傳入的引用實例化完全不同的類型。但是,您的示例會更改類的語義。您應該編輯它以真正反映OP正在做什麼,即保留第一個模板參數和繪製它的東西。另外請注意,在C++ 17中,由於構造函數將能夠指示其類的模板參數(因爲函數當前可以),所以'make_ *'函數將變得不必要。 –

相關問題