【发布时间】:2018-05-07 22:41:46
【问题描述】:
所以我有一个非模板base 类,其中包含其方法的“默认”设置。然后我尝试将继承与模板类一起使用。这是用于说明的示例代码的 sn-p。
// enums for as a template selector
enum class version
{
ver1,
ver2,
ver3
};
// Base class with fabricated methods
struct base
{
virtual void propertyOne()
{
// some default action
}
virtual void propertyTwo()
{
// some default action
}
};
// derived class
template <version V>
struct derived : public base
{
virtual void propertyOne()
{
helper< One, V >();
}
virtual void propertyTwo()
{
helper< Two, V >();
}
}
我正在使用辅助函数对类特征中使用的不同“字段”执行“通用”算法。
例如: 字段类似于此
struct field
{
int thingone;
constexpr field(int i):thingone(i){}
};
在 c++11 中,为了给字段实例提供外部链接,我将它们包装为另一个结构的静态成员(c++14 放宽了这些规则,哦,好吧)。我这样做的全部原因是因为我需要它的常量表达式值(例如,成员变量 thingone 需要作为另一个方法的模板参数,它要求它是一个常量表达式)。
struct fields
{
static constexpr field One{1};
static constexpr field Two{2};
};
// defining trait class from structure above
template< const field& T, revision R >
class fieldTraits;
// sample fieldTrait definitions for illustrative purposes
template< >
class fieldTraits< fields::One, revision::ver3>
{
public:
// Let's say I have common field names
// with different constants that I want to plug
// into the "helper" algorithm
static constexpr size_t field_val = 1;
};
template< >
class fieldTraits< fields::Two, revision::ver1>
{
public:
// Let's say I have common field names
// with different constants that I want to plug
// into the "helper" algorithm
static constexpr size_t field_val = 1;
};
// Main guts of the class methods above
template< const field& F, revision R, typename TT = traitClass<F,R> >
void helper()
{
// Let's pretend I'm doing something useful with that data
std::cout << F.thingone << std::endl;
std::cout << TT::field_val << std::endl;
}
我遇到的问题是尝试实例化例如
derived<revision::rev1> l_derived;
由于我只为ver3 定义了特征类,如果不明确定义ver1 和ver2 的特征类,我将无法实例化该类。但是,如果特征类对于 ver1 - ver 3 来说是完全相同的,那么是否有任何一种 enable_if 条件我必须使这个模板类对所有 revs <= ver3 都有效?
我在 traits_type 标头中找不到任何内容,该标头主要提供编译时“类型”检查,例如 std::is_same 等。
我知道一种选择是复制粘贴 ver1-ver3 的特征类,但这似乎是多余的,因为我想避免复制粘贴重复的代码。
另一种选择是为每个版本创建不同的类并利用动态多态性,我可以为每个版本定义一个类。然后我只需要在需要的地方包含特征修订更改。例如,
class derived_ver1 : public base
{
virtual void propertyOne()
{
helper< fields::One, revision::ver1 >();
}
virtual void propertyTwo()
{
helper< fields::Two, revision::ver1 >();
}
};
class derived_ver2 : public derived:ver1
{
virtual void propertyTwo()
{
helper< fields::Two, revision::ver2 >();
}
};
class derived_ver3 : public derived:ver2
{
virtual void propertyTwo()
{
helper< Two, revision::ver3 >();
}
};
在此示例中,propertyOne() 可以将修订版 1 中的特征类重用于修订版 2 和修订版 3,因为它在修订版 1 之前没有更改(并且避免复制粘贴特征)。
有没有更好的设计我可以接近?
总而言之:有没有办法使用我原来的模板继承并使用一些模板功能(例如std::enable_if)来重用一个特征类来进行未定义的修订。而不是为每个修订明确定义一个特征(这会导致复制粘贴)。
或者使用动态多态性的第二种方法是更好的方法(我读到,它增加了 vtable 查找的成本)?
【问题讨论】:
-
您的目标并不完全清楚。当您不声明/定义最直接提供属性的成员时,您希望
fieldTraits和/或在helper中使用TT退回到不同的结果?基于以前的revision值和/或一些整体默认值?如果您提供一张表格,说明您在其中为所有九个专业写了TT::field_val,可能会有所帮助? -
我修改了我的问题,如果可能的话,我希望帮助者回退到一个基地。例如,将修订版 3 特征用于未定义的修订版 2 或修订版 1 特征类。我认为答案是否定的……你不能这样做,但想验证一下。我认为这些专业的 field_val 值对我的问题不重要吗?
-
对不起,我还是不明白。你希望
TT::field_val在helper<fields::One, revision::ver2>()和helper<fields::Two, revision::ver2>()中做什么,为什么? (你有时有version,有时有revision,但看起来这些应该是一样的?)
标签: c++ c++11 templates polymorphism typetraits