我正在编写一个很大程度上依赖于类型参数化的C ++库。到目前为止,通过库参数化了四种类型。重要的是,并非每个类型组件都使用每种类型(即相关类的集合)。在下面的问题说明中,Component2
独立于C
类型至关重要。请注意,在下面的代码段中,可以从Component1
的不兼容实例中获取Component3
的类型兼容实例,因为D
调用会删除类型build_something()
。鉴于此要求,不可能对所有类模板使用相同的四种类型列表
template <typename A, typename B, typename C>
class Component1;
template <typename A, typename B, typename D>
class Component2;
template <typename A, typename B, typename C, typename D>
class Component3;
template <typename A, typename B, typename C>
class Component1 {
void augment(const Component1&);
}
template <typename A, typename B, typename D>
class Component2 {
template <typename D>
Component3<A, B, C, D> process_something(const Component1<A, B, C>&, const D&);
}
template <typename A, typename B, typename C, typename D>
class Component3 {
Component2<A, B, D> build_something(const B&) const;
}
// Choose some application-specific set of type substitions.
using a = ...;
using b = ...;
using c = ...;
using d1 = ...;
using d2 = ...;
d1 d1_instance;
d2 d2_instance;
// Make some objects.
Component3<a, b, c, d1> c3_first;
Component3<a, b, c, d2> c3_second;
// Get type-compatible objects below from type-incompatible objects above.
Component1<a, b, c> c1_first = c3_first.build_something(d1_instance);
Component1<a, b, c> c1_second = c3_second.build_something(d2_instance);
c1_first.augment(c1_second);
当然,重复所有这些类型列表变得不合适。我选择在类体外提供函数定义(即使类是模板)。此外,类型名称实际上是库实现中的整个单词,而不是单个字母。最后,此示例中的每个类都是实际库中一组类的替代。虽然根据这些方案之一进行了类型参数化,但是有许多类。我将在稍后添加更多方案。结果是代码,尤其是方法原型中的代码非常密集,难以维护甚至无法读取。
我正在寻找一个明确,有效且符合惯例的解决方案。我正在考虑以下解决方案,但我想知道是否有更清晰,更有效或更传统的解决方案。
我的候选解决方案是将相关类型分组到模板&#34;元类型&#34;,如下所示types1
和types2
:
template <typename A, typename B, typename C>
struct types1;
template <typename A, typename B, typename D>
struct types2;
class <typename types>
Component1;
class <typename types>
Component2;
然后可以从高级复合类型中提取较低级别的类型(尽管简单地将typdef放在元类型中也是有效的):
template <typename T>
struct get_A;
template <A, B, C>
struct get_A<type1<A, B, C>> {
using type = A;
}
template <A, B, D>
struct get_A<type2<A, B, D>> {
using type = A;
}
然后以下断言成立,因为get_A
从A
组合中获取types1
成分:
static_assert(std::is_same<int, typename get_A<types1<int, float, void>>::type>::value);
这个系统使得定义类内部结构变得更加简单,在统一不同方案的函数调用中增加了一些难度。一个严重的问题是,如果没有概念的语言级别约束(例如Concept Lite),则不可能简单地查看类模板定义并知道应该在types
模板参数中应该做什么。当然还有其他问题使这种方法远非完美解决。
有更好的方法吗?