I'm experimenting with C++ 20's concepts for the first time in a small side project of mine. I'm building an asset loader and manager system and am playing with concepts to make it cleaner.
I'm trying to make a concept that will guarantee that all valid "AssetTypes" have access to a static function that matches the format Handle<T> LoadAssetFromFile(const std::string& filepath)
.
For example, this Model class:
class Model : public RefType
{
...
public:
static Handle<Model> CreateModelFromPrimative(PrimitiveFunc primative, bool useIndex = true, Vec3 colour = { 1,1,1 });
static Handle<Model> LoadAssetFromFile(const std::string& filepath);
};
In this case, you can load a model from file or create one from a PrimitiveFunc
(just a typedef
for a function pointer), the asset system only requires that the from file method exists. Thus, I could run something similar to this:
template <AssetType T>
Handle<T> golem::AssetManager::GetAsset(const std::string& index)
{
...
// attempt to load asset from file using index as file path
Handle<T> assetHandle = T::LoadAssetFromFile(index);
...
}
So to finally address the question: How would I go about defining a concept that would allow this? Or is this even possible?
I have tried looking around online and in the docs and such, and the best I could find was this question C++ Concepts - Can I have a constraint requiring a function be present in a class? However, this question only applies to non-static methods.
The best I could come up with was this:
template <typename T>
concept AssetType = ReferenceType<T> && std::same_as<decltype(&T::LoadAssetFromFile), Handle<T>(*)(const std::string&)>;
I guess ,for transparency, I should say that the reference type concept is just:
template <typename T>
concept ReferenceType = std::is_base_of<RefType, T>::value;
which the model class does indeed apply too.
However, the implementation of the AssetType
concept shown above shows the following error when used with the afore mentioned model class:
What am I doing wrong here?