如何使用 std::enable_if_t & std::is_base_of 为 SFINAE 检查编译时继承?
How to check at compile-time inheritance using std::enable_if_t & std::is_base_of for SFINAE?
我试图在编译时将函数的模板类型限制为特定的 class 及其子 classes。为此,我使用类型特征 std::enable_if_t
和 std::is_base_of
,如下所示:
template <typename T = std::enable_if_t<std::is_base_of<A, T> > >
但是模板仍然使用不属于继承层次结构的类型(即 int
)进行编译。以下是问题的 MCVE:
class A {
public:
A(float a) : a(a) {}
float a;
};
class B : public A{
public:
B(float a) : A(a) {}
};
template <typename T = std::enable_if_t<std::is_base_of<A, T> > >
void templateFunction(T a) {
}
int main() {
templateFunction<A>(A(1.0f)); // OK -> std::is_base_of<A, A>
templateFunction<B>(B(1.0f)); // OK -> std::is_base_of<A, B>
templateFunction<int>(1); // Should not compile! int is not a subclass of A -> std::is_base_of<A, int>
return 0;
}
这个在Visual Studio 2017下编译没有任何错误,但是模板函数的最后一个实例在我看来应该编译不通过。
我对类型特征的使用是否有任何问题,或者 Visual Studios SFINAE 实现是否有问题?
你对enable_if的使用有点奇怪,我会这样做:
template <typename T>
std::enable_if_t<std::is_base_of<A, T>::value> templateFunction(T a) {
}
更好的解决方案:完全忘记 SFINAE:
template <typename T>
void templateFunction(T a) {
static_assert(std::is_baseOf<A,T>(), "only subclasses, please");
}
编辑,解释:把enable_if_t当成满足条件的东西(默认为void
)。
应用这个,你的函数读作:
// true case:
template <typename T = void>
void templateFunction(T a) {}
// false case:
template <typename T = nonsense>
void templateFunction(T a) {}
您的调用仍然与错误情况下的模板匹配!
现在,将其应用到我建议的代码中:
//true case:
template <typename T>
void templateFunction(T a) {}
//false case:
template <typename T>
*nonsense* templateFunction(T a) {}
这里,函数在 false 的情况下根本不存在,所以会产生编译错误。
我试图在编译时将函数的模板类型限制为特定的 class 及其子 classes。为此,我使用类型特征 std::enable_if_t
和 std::is_base_of
,如下所示:
template <typename T = std::enable_if_t<std::is_base_of<A, T> > >
但是模板仍然使用不属于继承层次结构的类型(即 int
)进行编译。以下是问题的 MCVE:
class A {
public:
A(float a) : a(a) {}
float a;
};
class B : public A{
public:
B(float a) : A(a) {}
};
template <typename T = std::enable_if_t<std::is_base_of<A, T> > >
void templateFunction(T a) {
}
int main() {
templateFunction<A>(A(1.0f)); // OK -> std::is_base_of<A, A>
templateFunction<B>(B(1.0f)); // OK -> std::is_base_of<A, B>
templateFunction<int>(1); // Should not compile! int is not a subclass of A -> std::is_base_of<A, int>
return 0;
}
这个在Visual Studio 2017下编译没有任何错误,但是模板函数的最后一个实例在我看来应该编译不通过。 我对类型特征的使用是否有任何问题,或者 Visual Studios SFINAE 实现是否有问题?
你对enable_if的使用有点奇怪,我会这样做:
template <typename T>
std::enable_if_t<std::is_base_of<A, T>::value> templateFunction(T a) {
}
更好的解决方案:完全忘记 SFINAE:
template <typename T>
void templateFunction(T a) {
static_assert(std::is_baseOf<A,T>(), "only subclasses, please");
}
编辑,解释:把enable_if_t当成满足条件的东西(默认为void
)。
应用这个,你的函数读作:
// true case:
template <typename T = void>
void templateFunction(T a) {}
// false case:
template <typename T = nonsense>
void templateFunction(T a) {}
您的调用仍然与错误情况下的模板匹配!
现在,将其应用到我建议的代码中:
//true case:
template <typename T>
void templateFunction(T a) {}
//false case:
template <typename T>
*nonsense* templateFunction(T a) {}
这里,函数在 false 的情况下根本不存在,所以会产生编译错误。