【发布时间】:2016-01-05 05:33:30
【问题描述】:
我想在拥有派生类实例的对象中获取基类的模板化类型。下面的代码 sn-p 不起作用,因为 Base 及其 ArbitraryType 无法通过 DerivedString 引用。 (标有感叹号的线)。但是,它绝对可以从它自己的模板类型 (OneOfTheDerivedTypes) 中推断出来。在我的情况下,我打算继承具有已定义模板的 AnotherObject,因此我不想将返回类型硬编码为 GetSomethingFromThingy()。
// -------------------
// Provided by my API:
// -------------------
template <typename ArbitraryType>
class Base {
virtual void DoSomething(ArbitraryType);
};
template <typename OneOfTheDerivedTypes>
class AnotherObject<OneOfTheDerivedTypes> {
// Other functions that perform useful tasks are here so that
// classes that inherit from AnotherObject need not implement them.
void SomethingMagical();
// A function with a specific return type.
virtual DerivedString::Base::ArbitraryType GetSomethingFromThingy() = 0; /* ! */
protected:
OneOfTheDerivedTypes thingy;
};
// --------------------------------------
// Someone using my API would make these:
// --------------------------------------
class DerivedFloat : public Base<float> {
void DoSomething(float) override;
};
class DerivedString : public Base<string> {
void DoSomething(string) override;
};
class UsefulObject : public AnotherObject<DerivedString> {
// Knows the required return type of GetSomethingFromThingy() without
// needing to specify it as a template. Should throw compile-time error
// if you tried to override with a different return type. In other words,
// forces return type to be string because of use of DerivedString.
string GetSomethingFromThingy() override;
};
对此的一种解决方案是指定一个名为 ArbitraryType 的附加模板参数,如下所示:
template <typename OneOfTheDerivedTypes, typename ArbitraryType>
class AnotherObject<OneOfTheDerivedTypes> {
virtual ArbitraryType GetSomethingFromThingy() = 0;
protected:
OneOfTheDerivedTypes thingy;
};
class UsefulObject<DerivedString, string> : public AnotherObject<DerivedString, string> {
string GetSomethingFromThingy() override;
};
然后程序员必须指定这两个参数,其中 OneOfTheDerivedTypes 是 DerivedFloat 或 DerivedString,而 ArbitraryType 分别是浮点数或字符串。这不是一个好的解决方案,因为 ArbitraryType 完全由 OneOfTheDerivedTypes 的选择指定。
我认为可以通过让 Base 在公共函数中返回 ArbitraryType 的实例(称为 ReturnInstanceOfArbitraryType())并在 AnotherObject 中使用 decltype(OneOfTheDerivedTypes::ReturnInstanceOfArbitraryType()) 来避免额外的模板(AnotherObject 中的 ArbitraryType)。这似乎不优雅,因为 ReturnInstanceOfArbitraryType() 在其他情况下没有用(并且必须是公共的)。在这种情况下,正确的做法是使用特征类吗?有更好的解决方案吗? (仍然掌握了一些新的 C++11 东西)。谢谢!
【问题讨论】:
-
在
Base内部,您可以稍后在派生类中使用typedef ArbitratyType TypeOfBase,您可以在第一个示例中使用TypeOfBase而不是DerivedString::Base::ArbitraryType。 -
啊,是的。效果很好,请随时在下面回答。它坚持我使用'typename DerivedType::TypeOfBase',这有点不幸。似乎它应该能够从它的使用方式和它是一个 typedef 的事实来判断它是一个类型。我在这里阅读更多关于它的信息:stackoverflow.com/questions/7923369/…
-
一个 using 声明可以帮助清理 typename 关键字: using TypeOfBase = typename DerivedType::TypeOfBase
标签: templates c++11 typetraits decltype