2017-04-13 110 views
1

所以我有一堆shared_ptr作为一个名为'Handler'的类的私有成员,每个类都指向不同的模板缓存类。像这样:C++ 11/14基于模板类型在单个函数中执行不同的操作

shared_ptr< Cache<T1> > t1Cache; 
shared_ptr< Cache<T2> > t2Cache; 
shared_ptr< Cache<T3> > t3Cache; 

每个Cache类简单地保持了与字符串作为一个键和T作为项目和功能来获得/更新和添加项目到地图的地图。我想在'Handler'中有一个成员函数来进行更新,添加和获取操作。所以,我可以打电话给例如:(凡ITEM_TYPE是一个枚举)

Handler handler; 
auto something = handler.getItem(key1, TYPE_T1); 
handler.addItem(key2, TYPE_T2, newItem); 
handler.updateItem(key3, TYPE_T3, newValue); 

我试图在基于枚举像这样第一只具有开关:

template <typename T> 
auto addItem(const std::string& key, ITEM_TYPE type, T nItem) 
{ 
    switch(type) 
    { 
    case TYPE_T1: 
     t1Cache->addItem(key, nItem); 
    break; 
    case TYPE_T2: 
     t2Cache->addItem(key ,nItem); 
    break; 
    } 
} 

不幸的是我的基本知识模板,所以我没有意识到这是行不通的。目前作为一种临时解决方案,即使我为每种类型使用不同的功能,但我真的很想将它们合并为一个。我认为也许'constexpr if'会有帮助,但不被支持,这甚至有可能吗?

编辑:对不起标题是不是真的措辞吧,不知道如何标题此

+0

什么是'ITEM_TYPE'?这听起来像一个枚举或int。您需要**类型**不能使模板工作。刚开始时很难缠住你的头。 – AndyG

+1

目前还不清楚你的功能是什么意思,难以回答这个问题。你也可能想描述你想要完成的事情,但不清楚模板在这里是否合适。 – jhauris

+0

做这些不同的功能看起来/行为有什么不同吗?你的'Cache'类是什么样的? – AndyG

回答

2

这样的事情呢?

#include <string> 
#include <tuple> 

template <class T> class Cache 
{ 
public: 
    void addItem(std::string const& key, T item) 
    { 
    } 
}; 

template <class... T> class SuperCache 
{ 
public: 
    template <class U> void addItem(std::string const& key, U&& item) 
    { 
    std::get<Cache<std::decay_t<U>>>(caches_).addItem(key, std::forward<U>(item)); 
    } 

private: 
    std::tuple<Cache<T>...> caches_; 
}; 

int main() 
{ 
    SuperCache<int, double> cache; 
    cache.addItem("a", 5); 
    cache.addItem("b", 5.0); 
} 

如果你可以使用C++ 17,那么这里的另一种方法(根据您的需求),可能的工作:

#include <string> 
#include <unordered_map> 
#include <variant> 

template <class... T> class VariantCache 
{ 
public: 
    template <class U> void addItem(std::string const& key, U&& item) 
    { 
    items_[key] = std::forward<U>(item); 
    } 

private: 
    std::unordered_map<std::string, std::variant<T...>> items_; 
}; 

int main() 
{ 
    VariantCache<int, double> cache; 
    cache.addItem("a", 5); 
    cache.addItem("b", 5.0); 
} 
+0

谢谢,第一种方法完美无缺! – Xsy

1

我不知道你为什么会想这样做,但你可以封装所有的缓存到一个数组和使用在函数中get<T>选择适当的元组元素:

#include <memory> 
#include <tuple> 
#include <vector> 
#include <iostream> 

template<class T> struct Cache 
{ 
    std::vector<T> x; 
    void add(T const& y) { x.push_back(y); } 
}; 

template<class T1, class T2, class T3> 
struct test 
{ 
    test() : _caches(std::make_tuple(std::make_shared<Cache<T1>>(), 
     std::make_shared<Cache<T2>>(), std::make_shared<Cache<T3>>())) {} 
    std::tuple<std::shared_ptr<Cache<T1>>, std::shared_ptr<Cache<T2>>, 
     std::shared_ptr<Cache<T3>>> _caches; 
    template<class T> 
    void add_item(T const& v) 
    { 
     std::get<std::shared_ptr<Cache<T>>>(_caches)->add(v); 
    } 
}; 

int main() 
{ 
    test<int, float, double> a; 
    a.add_item(1); 
    std::cout << std::get<std::shared_ptr<Cache<int>>>(a._caches)->x.size() << "\n"; 
    return 0; 
} 

注意get<T>如果元组包含T类型的多个项目,所以这种解决方案需要T1T2T3是明显不编译。

相关问题