Search code examples
c++sfinae

How can I use SFINAE to disable a function inside a class based on template type


I have a template class

template<typename TLoader, typename TCreator>
class ManagerGroup {
public:
  uint32_t loadFromPath(const Path &path) {
    return mLoader.load(path);
  }

  void createFile(uint32_t handle) {
    return mCreator.create(handle);
  }

private:
  TLoader mLoader;
  TCreator mCreator;
};

For the loadFromPath and createFile functions, I want to disable them if the provided typename is std::nullptr_t; so, I can do something like this:

ManagerGroup<FontLoader, std::nullptr_t> fontManager;

// No issues
fontManager.loadFromPath("/test");

// Compilation error
fontManager.createFile(10);

ManagerGroup<std::nullptr_t, MeshCreator> meshManager;

// NO issues
meshManager.createFile(20);

// Throws error
meshManager.loadFromFile("/test");

Is this possible with SFINAE?

I tried the following but could not get it working (based on example #5 in https://en.cppreference.com/w/cpp/types/enable_if):

template<typename = std::enable_if_t<!std::same<TCreator, std::nullptr_t>::value>>
void createFile(uint32_t handle) {
  return mCreator.create(handle);
}

Solution

  • In order for SFINAE to work you need to use a parameter that is being deduced. In your case TCreator is already known so you can't use it. You can instead get around the problem by adding your own parameter and defaulting it to TCreator like

    template<typename T = TCreator,
             std::enable_if_t<!std::is_same_v<T, std::nullptr_t>, bool> = true>
    void createFile(uint32_t handle) {
      return mCreator.create(handle);
    }