所以我有一个非模板 base
包含其方法的“默认”设置的类。然后我尝试将继承与模板化类一起使用。以下是用于说明的示例代码片段。
// 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 header 中找不到任何内容,它主要提供编译时“类型”检查,例如 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 查找的成本)?
最佳答案
我很难理解你想要什么;请修改您的问题以检查详细信息(version
和 revision
是一样的吗?fieldTraits
和 traitsClass
是一样的吗?)。
无论如何,如果我理解正确的话,你想为
定义一个特化template <const field& T, revision R>
class fieldTraits;
当R
是val1
或 val2
或 val3
并且,也许还有针对单个以下值的其他特化。
假设你有四次修改
enum class revision { ver1, ver2, ver3, ver4 };
可以声明fieldTraits
(作为 struct
,使其更短)添加 bool
表示 if R <= revision::ver3
的默认模板参数
template <field const & T, revision R, bool = (R <= revision::ver3)>
struct fieldTraits;
现在您可以为 ver1
开发特化, ver2
和 ver3
template <field const & T, revision R>
struct fieldTraits<T, R, true>
{ static constexpr size_t field_val = 1; };
和 ver4
的特化
template <field const & T>
struct fieldTraits<T, revision::ver4>
{ static constexpr size_t field_val = 2; };
下面是一个简化但完整的例子
#include <iostream>
enum class revision { ver1, ver2, ver3, ver4 };
struct field
{
int thingone;
constexpr field (int i) : thingone(i)
{ }
};
template <field const & T, revision R, bool = (R <= revision::ver3)>
struct fieldTraits;
// version ver1, ver2, ver3 cases
template <field const & T, revision R>
struct fieldTraits<T, R, true>
{ static constexpr size_t field_val = 1; };
// version ver4 case
template <field const & T>
struct fieldTraits<T, revision::ver4>
{ static constexpr size_t field_val = 2; };
static constexpr field f{1};
int main ()
{
std::cout << "ver1: " << fieldTraits<f, revision::ver1>::field_val
<< std::endl;
std::cout << "ver2: " << fieldTraits<f, revision::ver2>::field_val
<< std::endl;
std::cout << "ver3: " << fieldTraits<f, revision::ver3>::field_val
<< std::endl;
std::cout << "ver4: " << fieldTraits<f, revision::ver4>::field_val
<< std::endl;
}
打印
ver1: 1
ver2: 1
ver3: 1
ver4: 2
-- 编辑 --
根据 OP 的评论,我提出了一些不同的解决方案
template <field const & T, revision R, typename = std::true_type>
struct fieldTraits;
// version ver1, ver2, ver3 cases
template <field const & T, revision R>
struct fieldTraits<T, R, std::integral_constant<bool, (R <= revision::ver3)>>
{ static constexpr size_t field_val = 1; };
// version ver4 case
template <field const & T>
struct fieldTraits<T, revision::ver4>
{ static constexpr size_t field_val = 2; };
关于c++,我可以使用 enable_if 而不是复制粘贴来启用多个特征类特化吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50223447/