具有 built-in 缓存的 C++ object 工厂 - 阴影模板参数
C++ object factory with built-in cache - shadows template parameter
我有一个数据库 class,它应该为 return 存储库 objects 提供一个模板方法来表示表。每个存储库应仅存在一次。我找到了 this 示例,但我想要一个 built-in 缓存。
database.h
header 看起来像这样:
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。
class RepositoryBase
{
public:
RepositoryBase(sqlite3* connection);
virtual string GetTableName() = 0;
protected:
sqlite3* _connection;
};
这里的问题是
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();
我有一个数据库 class,它应该为 return 存储库 objects 提供一个模板方法来表示表。每个存储库应仅存在一次。我找到了 this 示例,但我想要一个 built-in 缓存。
database.h
header 看起来像这样:
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。
class RepositoryBase
{
public:
RepositoryBase(sqlite3* connection);
virtual string GetTableName() = 0;
protected:
sqlite3* _connection;
};
这里的问题是
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();