具有内置缓存的C ++对象工厂 - 阴影模板参数

时间:2017-08-25 15:08:40

标签: c++ objectfactory

我是一个数据库类,它应该提供一个模板方法来返回表示表的存储库对象。每个存储库只能存在一次。我找到了this示例,但我希望有一个内置缓存。

database.h标题如下所示:

class Database
{
public:
  Database(const char *connectionString);
  template<typename T> shared_ptr<class T : RepositoryBase> GetRepository();

private:
  sqlite3* _connection;
  map<string, RepositoryBase> _repositoryCache;
};

GetRepository方法的实现如下:

template<typename T> shared_ptr<class T : RepositoryBase> Database::GetRepository()
{
  string name = typeid(T).name();

  if(_repositoryCache.count(name) == 0)
  {
    _repositoryCache[name] = shared_ptr<T>(new T(_connection));
  }

  return _repositoryCache[name];
}

我想这样称呼:

// SampleRepository is derived from RepositoryBase
shared_ptr<SampleRepository> sampleRepo = GetRepository<SampleRepository>();

当我编译时,我收到错误:

error : declaration of 'T' shadows template parameter

我需要在模板方法中更改哪些内容才能隐藏任何模板参数?

更新

在NathanOliver的建议之后,模板方法如下:

template<typename T, typename enable_if<is_base_of<RepositoryBase, T>::value>::type* = nullptr> shared_ptr<T> Database::GetRepository()
{
  string name = typeid(T).name();

  if(_repositoryCache.count(name) == 0)
  {
    _repositoryCache[name] = shared_ptr<T>(new T(_connection));
  }

  return _repositoryCache[name]();
}

这次我收到错误:

error : template parameter redefines default argument

它指向模板签名中的nullptr

更新2

我根据@NathanOliver给出的答案尝试了几种参数组合。我仍然得到错误:

1>C:\..\Database.cpp(65,98): error : template parameter redefines default argument
1>template<typename T, typename std::enable_if<std::is_base_of<RepositoryBase, T>::value>::type* = nullptr> std::shared_ptr<T> Database::GetRepository()
1>                                                                                                 ^
1>C:\..\Database.h(25,108) :  note: previous default template argument defined here
1>          template<typename T, typename std::enable_if<std::is_base_of<RepositoryBase, T>::value>::type* = nullptr> std::shared_ptr<T> GetRepository();
1>                                                                                                           ^

为了更好地理解,我还添加了存储库基类。

class RepositoryBase
{
public:
  RepositoryBase(sqlite3* connection);
  virtual string GetTableName() = 0;

  protected:
    sqlite3* _connection;
 };

1 个答案:

答案 0 :(得分:4)

这里的问题是

template<typename T> shared_ptr<class T : RepositoryBase> GetRepository();

在C ++中是无效的语法。如果您想将T限制为RepositoryBase或从RepositoryBase派生,那么您需要在template<typename T>部分中执行此操作。我们要做的是添加T类型的检查,如果检查失败,那么编译器将不会生成将导致编译器错误的函数。那看起来像是

template<typename T, typename std::enable_if<std::is_base_of<RepositoryBase, T>::value>::type* = nullptr> 
shared_ptr<T> GetRepository();