Using SFINAE to disable template class member function

|▌冷眼眸甩不掉的悲伤 提交于 2021-02-08 13:22:09

问题


Is it possible to use SFINAE and std::enable_if to disable a single member function of a template class?


I currently have a code similar to this:

#include <type_traits>
#include <iostream>
#include <cassert>
#include <string>

class Base {
public:
    virtual int f() { return 0; }
};

template<typename T>
class Derived : public Base {
private:
    T getValue_() { return T(); }

public:
    int f() override {
        assert((std::is_same<T, int>::value));
        T val = getValue_();
        //return val; --> not possible if T not convertible to int
        return *reinterpret_cast<int*>(&val);
    }
};


template<typename T>
class MoreDerived : public Derived<T> {
public:
    int f() override { return 2; }
};


int main() {
    Derived<int> i;
    MoreDerived<std::string> f;
    std::cout << f.f() << " " << i.f() << std::endl;
}

Ideally, Derived<T>::f() should be disabled if T != int. Because f is virtual, Derived<T>::f() gets generated for any instantiation of Derived, even if it is never called. But the code is used such that Derived<T> (with T != int) never gets created only as a base class of MoreDerived<T>.

So the hack in Derived<T>::f() is necessary to make the program compile; the reinterpret_cast line never gets executed.


回答1:


You could simply specialize f for int:

template<typename T>
class Derived : public Base {
private:
    T getValue_() { return T(); }

public:
    int f() override {
        return Base::f();
    }
};

template <>
int Derived<int>::f () {
    return getValue_();
}



回答2:


No you can't rule out a member function with SFINAE. You could do it with specialisation of your Derived class f member function for convertible Ts to int but that would lead to unnecessary duplication of code. In C++17 however you could solve this with use of if constexpr:

template<typename T> class Derived : public Base {
  T getValue_() { return T(); }
public:
  int f() override {
    if constexpr(std::is_convertible<T, int>::value) return getValue_();
    return Base::f();
  }
};

Live Demo



来源:https://stackoverflow.com/questions/38635776/using-sfinae-to-disable-template-class-member-function

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!