等效于C ++的typedef /别名在模板编程中的使用

时间:2016-08-05 14:35:50

标签: c# templates generics

我正在研究一个C#项目,发现自己试图在C ++中重现一个常见的模式,但到目前为止还没有。我正在尝试做的一个例子(在C ++中):

enum ProductItemTypes {
    Product,
    Family,
    SubFamily,
    Department
}; 

class ProductItem : PanelItem {
public:
    using item_type_t = ProductItemTypes;
    ...
};

enum PaymentItemTypes {
    Group,
    Valued,
    NotValued,
    Balance
};

class PaymentItem : PanelItem {
public:
    using item_type_t = PaymentItemTypes;
    ...
};

有不同的类继承自PanelItem并拥有自己的item_subtype_t。 然后,使用PanelItem的类可以知道相应的项类型并且通常可以工作。

在C#中具有某种类似的能力可以帮助我避免大量重复的代码,但我不想传递所有类型(ProductItemProductItemType,以及更多我一直都在排除简单性。

1 个答案:

答案 0 :(得分:2)

很难准确说出你的用例是什么,因为你还没有举例说明:

  

然后,使用PanelItems的类可以知道相应的项类型并一般地工作。

直接使用PanelItems的课程无法执行此操作。唯一的解决方法是,如果类是直接接受类型的模板类(我猜测的是你实际意味着发生的事情):

template<class T>
class Foo
{
public:
    using item_type_t = typename T::item_type_T;
}

你无法用C#做到这一点。虽然语法上的泛型和模板看起来非常相似,但它们是两种非常不同的野兽。对于您所做的每个不同的具体类型替换,都会编译一次C ++模板。这也是SFINAE发生的原因。基本上每次编译器看到模板的使用时,它都会在类型参数中替换并尝试重新编译类或方法。

另一方面,C#的泛型只编译一次,并且与类型参数无关。这就是C#中存在泛型约束的原因:它允许您为编译器提供有关它将要处理的类型类型的更多知识。这也意味着C#没有SFINAE的概念,因为编译器没有实际的替换。

我的观点是你目前的方法是漏洞。基本上,不同的item_type_t类型是派生类的实现细节,这些类的用户必须知道该类型是什么才能正确使用该类型。对我而言,这是打破封装,C ++只是提供了一种机制,通过隐藏程序员的类型知识来解决这种泄漏问题,并且只需要编译器实际知道它。

如果没有关于您正在尝试做什么的更多细节,很难就替代方法提出任何建议。我相信有一种替代设计可以干净地处理你的问题,但是现在这是一个XY问题。