我有一个模板类B,其第一个参数T1必须继承类A,第二个参数T2用于嵌套类C:
class A { ... };
template<typename T1, typename T2 = T1, typename = std::enable_if_t<std::is_base_of<A, T1>::value>>
class B {
class C {
T2 data;
C(T2 data);
void func();
...
};
...
};
问题是当我尝试定义嵌套类的构造函数和方法时出现错误:
template<typename T1, typename T2, typename>
B<T1, T2>::C::C(T2 data) : data(data) { ... }
template<typename T1, typename T2, typename>
void B<T1, T2>::C::func() { ... }
如果我不使用嵌套类或不使用 std::enable_if,代码可以正常工作,但在这里我需要它们,而且我真的不明白出了什么问题。
定义构造函数时仍然需要提供默认的模板参数:
template<typename T1, typename T2, typename D>
B<T1, T2, D>::C::C(T2 data) : data(data) { }
或者,由于最后一个参数仅用于 SFINAE 目的并且始终旨在为
void
,因此您可以编写:
template<typename T1, typename T2>
B<T1, T2, void>::C::C(T2 data) : data(data) { }
请注意,最好在
C
中定义构造函数。
无论如何,大多数时候你都无法将模板拆分为标头/源代码,并且处理类模板的外线定义可能非常烦人且脆弱。
如果您使用的是 C++20,您可以编写:
template<std::derived_from<A> T1, typename T2 = T1>
class B { /* ... */ };
template<std::derived_from<A> T1, typename T2>
B<T1, T2>::C::C(T2 data) : data(data) { }
如果您使用的是 C++17,您至少可以使用辅助变量模板
std::is_base_of_v<A, T1>
。