我有一个模板和许多派生类。在所有这些类中,我想使用模板类型和它的一些依赖类型(实际上我有很多类型和很多依赖类型)。
以下方法非常糟糕,因为我需要手动继承(使用 using 关键字)父类中的所有类型(参见代码示例):
编辑: 我不知道我想使用类型的类也是模板这一点很重要。我相应地更新了代码示例。
template<class T>
class A {
using TBase = T;
using TDerived = T[10];
}
template<class T>
class B : A<T> {
// NOTE i want the types TBase and TDerived here and in further children
using TBase = A<T>::TBase;
using TDerived = A<T>::TDerived
}
class C : B<int> {
// NOTE i want the types TBase and TDerived here and in further children
using TBase = B<int>::TBase;
using TDerived = B<int>::TDerived
}
我还考虑过模板化命名空间,这样我就可以在类之外定义类型 - 但它们不存在。
有没有人有更好的主意?
解决方案 1:修复当前方法
(基于 Jan Hudec 的评论和 Oguk 的回答)
- 公共(public)继承
我忘记了类的关键字public:
(默认情况下结构是公共(public)的)。 - 缺少
typename
编译器针对我在类中使用的(错误的)类型发出警告,这些警告具有误导性(尽管针对using
关键字的警告直接提示缺少typename 关键字
)。
有关何时使用typename
的更多说明,请参见此处:https://stackoverflow.com/a/7923419/3779655 - 类型交互
当我正确指定类型时(例如,参见 2.missingtypename
),我还可以使用当前的类名。
结果代码:
template<class T>
class A {
public:
using TBase = T;
using TDerived = T[10];
};
template<class T>
class B : public A<T> {
public:
// possiblity 1:
using TBase = typename B::TBase;
TBase memberB1;
// possibility 2
typename B::TBase memberB2;
};
class C : public B<int> {
public:
// NOTE C is no template -> we don't have to do anything
TBase memberC;
};
解决方案 2:特征类
(基于 Oguk 的回答)
- 使用模板化特征类而不是命名空间
这提供了几乎相同的功能。 - 类型信息的不同可用性
我之前没有想到的一件事是检查哪些类型信息在何处可用以及是否需要更多字符以从父类检索所需的类型信息(请参阅注释注释)。
见下面的代码:
template<class T>
struct TypesContainer {
using TBase = T;
using TDerived = T[10];
};
template<class T>
class A {
public:
// TODO possible to directly inherit all types?
//using TypesContainer<T>;
// NOTE this is only possible for methods, not types
using Types = TypesContainer<T>;
typename Types::TBase memberA;
};
class B : public A<int> {
public:
// NOTE here I have all template information via definition (by hand)
using Types = TypesContainer<int>;
typename Types::TBase memberB;
};
class C : public B {
public:
// NOTE here I don't have the type information any more
using Types = TypesContainer<A::Types::TBase>;
typename Types::TBase memberC;
};
问题:
有没有办法在类范围内直接继承命名空间/类的所有成员(参见 TODO 注释)。使用不带赋值运算符 =
的 using
关键字仅适用于方法,不适用于命名空间、类 和类型。
最佳答案
首先,如果您对自己的设计还满意,那么如果您公开继承基类,它应该可以工作。这将在您发布的代码中起作用。但是,如果您的示例非常简单,则可能还有另一个原因导致您无法在真实代码中访问 typedef:可能会给您带来问题的是,如果您的派生类实际上也是一个模板化类使用类型参数 T
,例如B<T>
.这将使基类 A<T>
如果您使用非依赖名称(即仅 TBase
)在 B<T>
中引用它们,则在查找过程中不会考虑 dependent 及其成员,所以他们不会被发现。将它们称为 typename A<T>::TBase
将通过使名称依赖名称来解决该问题。
如果你想遵循你的其他想法并在类之外提供该类型信息(因为它在概念上更多地连接到 T
而不是更多地连接到类 A
),而不是“模板化的命名空间"你在想,通常,特征类用于此目的:
template <class T>
struct MyTraits {
using TBase = T;
using TDerived = T[10];
}
然后你可以访问那些using
使用 typedefs
从任何地方声明(或者, MyTraits<T>::TBase
) .这实际上是您使用模板化 namespace 可以实现的。不要忘记添加 typename
关键字,如果你使用 MyTraits
的 using/typedef 成员在依赖上下文中,即 typename MyTraits<T>::TBase
.
关于C++ 继承模板依赖类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26744545/