我有这个班级
class AssetManager
{
private:
std::unordered_map<const std::type_info*, Asset*> assets;
public:
AssetManager();
virtual ~AssetManager();
template <typename T, typename ...Args>
bool newAsset(Args... args)
{
//Get path
if(cached(path)) { return true; }
auto asset = new T{ std::forward<Args>(args)... };
assets[&typeid(*asset)] = asset;
return *static_cast<T*>(assets[&typeid(T)]);
}
bool cached(const std::string& path)
{
for(auto asset : assets) {
if(asset.second->getPath() == path) {
return true;
}
}
return false;
}
};
每个Asset的第一个参数将始终是std :: string path。 我正在尝试获取此值,看看它是否已经加载到列表中。 资产是一个抽象类。
class Asset
{
private:
std::string path;
public:
Asset(const std::string& path);
virtual ~Asset() = default;
virtual bool load() = 0;
std::string getPath();
};
继承Asset的类可能有不同数量的参数,因此我试图捕获第一个参数的值,因为它总是一个std :: string路径,你可以在Asset类构造函数中看到。
答案 0 :(得分:5)
如果你的第一个参数总是一个std :: string,那么以这种方式声明是很有意义的。首先,它解决了这个问题。另一方面,它确保来电者永远不会错。如果你在资产的构造函数中也需要它,或者将它单独传递给那个构造函数,或者只是在那里声明它。
template <typename T, typename ...Args>
bool newAsset(const std::string &path, Args&&... args)
{
//Get path
if(cached(path)) { return true; }
auto asset = new T{ path, std::forward<Args>(args)... };
assets[&typeid(*asset)] = asset;
return *static_cast<T*>(assets[&typeid(T)]);
}
我也想知道你对typeid的使用;你绝对肯定使用它作为地图中的键是正确的吗?我没有看到任何运算符&lt;,并且运营商==无法保证根据http://en.cppreference.com/w/cpp/language/typeid(在&#39;注释&#39;)下提供一致的结果。最好使用typeid.hash_code()
代替。
答案 1 :(得分:0)
cached
查找Asset
构造函数
template <typename T, typename ...Args>
bool newAsset(const std::string& path, Args&&... args)
{
if(cached(path)) { return true; }
auto asset = new T{ path, std::forward<Args>(args)... };
assets[&typeid(*asset)] = asset;
return *static_cast<T*>(assets[&typeid(T)]);
}
答案 2 :(得分:0)
虽然标记的答案对于问题中描述的情况是正确的,但我最近遇到了一种情况,即不从包中拆分第一个参数会更方便。
我使用的解决方案是
template <typename... T>
void f(T&&... values)
{
using FirstType = std::tuple_element_t<0, std::tuple<T...>>;
...
}
当您确实需要完全按照问题要求执行时,我将其添加到此处作为(不可否认的)案例的参考。
请注意,该函数要求至少有一个参数被调用,没有参数的调用将无法编译。