是否可以使用SFINAE和std::enable_if
来禁用模板类的单个成员函数?
我目前有类似的代码:
#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;
}
理想情况下,如果Derived<T>::f()
,则应禁用T != int
。由于f
是虚拟的,因此Derived<T>::f()
的任何实例化都会生成Derived
,即使它从未被调用过。
但是使用的代码使得Derived<T>
(带T != int
)永远不会仅作为MoreDerived<T>
的基类创建。
因此,Derived<T>::f()
中的hack是编译程序所必需的; reinterpret_cast
行永远不会被执行。
答案 0 :(得分:6)
您可以简单地为f
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_();
}
答案 1 :(得分:5)
不,你不能排除SFINAE的会员功能。您可以通过将Derived
类f
成员函数专门化为可转换T
到int
来实现此目的,但这会导致不必要的代码重复。但是在C ++ 17中,您可以使用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();
}
};