我有以下尝试使用
enable_if
来实例化 A
类的 2 个不同专业化的示例,但我不正确理解它,因为它们没有被调用,有什么建议吗?
#include <type_traits>
#include <iostream>
class SC1 {
public:
SC1() {
std::cout << "SC1\n";
}
};
class SC2 {
public:
SC2() {
std::cout << "SC2\n";
}
void f() {};
};
template <class T, typename TC1 = void, class TC2 = void>
class A {
public :
A() {
std::cout << "default A\n";
};
};
template <class T>
class A <T, typename std::enable_if_t<T::SC1_ENABLE, typename T::EN>, void> : public T::EN {
static_assert(!std::is_same<typename T::EN, SC1>::value);
public:
A() {
std::cout << "1 type is " << typeid(typename std::enable_if_t<T::SC1_ENABLE>).name() << "\n";
}
};
template <typename T>
class A <T, void, typename std::enable_if_t<T::SC2_ENABLE, typename T::EN>> : public T::EN {
public:
A() {
static_assert(std::is_same<typename T::EN, SC2>::value);
//std::cout << "2 type is " << typeid(typename std::enable_if_t<T::SC2_ENABLE>).name() << "\n";
}
};
struct T1 {
static constexpr bool SC1_ENABLE = false;
static constexpr bool SC2_ENABLE = false;
};
struct T2 {
static constexpr bool SC1_ENABLE = true;
static constexpr bool SC2_ENABLE = false;
typedef SC1 EN;
};
struct T3 {
static constexpr bool SC2_ENABLE = true;
static constexpr bool SC1_ENABLE = false;
typedef SC2 EN;
};
int main() {
// std::enable_if_t<T3::SC2_ENABLE,T3::EN>();
A<T3>();
A<T2>();
}
我尝试了它的不同变体,使用 GCC 使用 c++ std 20 编译它,并且仅调用
A
的默认实现。
您使用了
std::enable_if
错误。
在主模板中,您使用
typename TC1 = void
作为模板参数(顺便说一下,可以将其简化为 typename = void
)。
为了让 A<T2>()
(相当于 A<T2, void, void>()
)使用第一个部分特化,部分特化也必须有 void
。
但是,您使用的是
typename std::enable_if_t<T::SC1_ENABLE, typename T::EN>
,这是替换后的 T::EN
类型,因此这永远不会匹配。
一旦你写了它就起作用了:
std::enable_if_t<T::SC1_ENABLE>
请注意,
void
是第二个模板参数的默认参数,typename
是不必要的。
但是,这将放弃
T::EN
必须是类型的要求,因此您可以编写如下内容:
template <typename>
inline constexpr bool tru = true;
// ...
template <class T>
class A <T, std::enable_if_t<T::SC1_ENABLE && tru<typename T::EN>, void> : public T::EN {
还请记住,针对不同的要求使用两个单独的
void
不会在它们之间强加某种顺序,这可能会在您面前爆炸。
请参阅为类型特征排序多个 std::void_t 部分特化的可靠方法以获得可靠的解决方案