使用 SFINAE 禁用模板 class 成员函数
Using SFINAE to disable template class member function
是否可以使用 SFINAE 和 std::enable_if
禁用模板的单个成员函数 class?
我目前有一个类似这样的代码:
#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;
}
理想情况下,如果 T != int
,则应禁用 Derived<T>::f()
。因为 f
是虚拟的,所以 Derived
的任何实例化都会生成 Derived<T>::f()
,即使它从未被调用。
但是使用代码使得 Derived<T>
(带有 T != int
)永远不会仅作为 MoreDerived<T>
.
的基础 class 创建
因此 Derived<T>::f()
中的 hack 是编译程序所必需的; reinterpret_cast
行永远不会执行。
不,您不能排除 SFINAE 的成员函数。您可以通过将 Derived
class 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();
}
};
您可以简单地将 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_();
}
是否可以使用 SFINAE 和 std::enable_if
禁用模板的单个成员函数 class?
我目前有一个类似这样的代码:
#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;
}
理想情况下,如果 T != int
,则应禁用 Derived<T>::f()
。因为 f
是虚拟的,所以 Derived
的任何实例化都会生成 Derived<T>::f()
,即使它从未被调用。
但是使用代码使得 Derived<T>
(带有 T != int
)永远不会仅作为 MoreDerived<T>
.
因此 Derived<T>::f()
中的 hack 是编译程序所必需的; reinterpret_cast
行永远不会执行。
不,您不能排除 SFINAE 的成员函数。您可以通过将 Derived
class 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();
}
};
您可以简单地将 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_();
}