2

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:

visual studio error screenshot

What am I doing wrong here?

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
JayMarBu
  • 21
  • 3
  • 1
    If the question is about something related to a class static function, what relevance do all those class members, shared_ptrs, inner classes, and other objects have anything to do with anything? I have a feeling that you can get rid of 90% of the shown code, that is not related to the question being asked, and result in a much clearer, and easier to understand question. As such, all that visual clutter is distracting from the subject matter being asked. – Sam Varshavchik Jul 24 '22 at 21:25
  • @SamVarshavchik sorry about that, ive cleaned up the code snippets to be more concise, hope this makes it better – JayMarBu Jul 24 '22 at 21:37

1 Answers1

0

In the question you linked to, the code in the question was actually doing what you wanted (but not what the other question wanted).

The presence of additional templates does add a little bit of confusion, though, but compare this with that other question:

Live demo

#include <string>
#include <type_traits>
#include <concepts>

template<typename T> class Handle {};

template<typename T>
concept AssetType = requires(const std::string &f) {

    { T::LoadAssetFromFile(f) } -> std::same_as<Handle<T>>;
};


class Model {

public:

    static Handle<Model> LoadAssetFromFile(const std::string& filepath);
};

class NotModel {};


template<AssetType a> class uses_asset {};

uses_asset<Model> ok;

/// COMPILATION ERROR:
//
// uses_asset<NotModel> error;

int main()
{
}
Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148