带有 std::enable_if 的嵌套模板类,C++

问题描述 投票:0回答:1

我有一个模板类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() { ... }
  1. E0464“B::value, void>>::C”不是类模板;
  2. C3860 类类型名称后面的类型参数列表必须按照类型参数列表中使用的顺序列出参数。

如果我不使用嵌套类或不使用 std::enable_if,代码可以正常工作,但在这里我需要它们,而且我真的不明白出了什么问题。

c++ templates inheritance nested enable-if
1个回答
0
投票

定义构造函数时仍然需要提供默认的模板参数:

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++17 和 C++20 的注意事项

如果您使用的是 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>

© www.soinside.com 2019 - 2024. All rights reserved.