用于约束类型模板参数的惯用方法是什么,以便它只接受特定模板的实例化?
如,
template<typename P>
class C {
C() = default;
...
};
template<typename T>
class Accepted {
...
};
template<typename T>
class Other {
...
};
C<Accepted<float>> obj1; // should compile
C<Accepted<int>> obj2; // should compile
C<Other<int>> obj3; // should not compile
C<double> obj4; // should not compile
答案 0 :(得分:3)
专业化是答案。
template<typename P> class C;
template<typename T>
class Accepted {
...
};
template<typename P>
class C<Accepted<P>> {
C() = default;
...
};
以上使得C<Accepted<T>>
格式正确,因为它在实例化时选择了特化。虽然任何其他C<T>
选择了未定义的主要特化,因此不会编译。
答案 1 :(得分:2)
我在不了解更多相关背景的情况下看到了两个可能的答案。
template<typename T> class C;
template<template<typename> typename TT, typename T> class C<TT<T>> {
... static_assert(std::is_same<TT<T>, Accepted<T>>::value, "The given type is not an instantiation of Accepted!"); ...
}
这只是非常有用 - 接受的特别之处是什么?您可能有第二个模板,例如SortedAccepted<T>
,符合相同要求,但您已着手将模板参数约束为Accepted<T>
。
一种选择是将Accepted设计为契约,以便它的派生必须满足与Accepted本身相同的约束:
template<template<typename> typename TT, typename T> class C {
... static_assert(std::is_base_of<Accepted<T>, TT<T>>::value,
"The given type is not a derivation of Accepted!"); ...
};
这是从设计原则得出的结论,即Accepted应该通过其派生来扩展,但不能被修改。从前面的示例中,可能Accepted需要具有幂等“排序”方法 - accepted.sort().sort() == accepted.sort()
- 而SortedAccepted隐式保留此属性,但另外提供sorted_accepted.sort() == sorted_accepted
。在允许排序接受的地方你没有什么可失去的,只要你期望接受,但可以获得很多!
如果我理解你的问题,你可能会对Traits and Concepts感兴趣。
在<type_traits>
和Boost's extensions中看到的类型特征是reified合同,提供有关集合共享特征,这些特征的表达式等的编译时保证。例如S s; T t; auto u = s + t
std::is_arithmetic<S>::value
和std::is_arithmetic<T>::value
为真,保证std::is_arithmetic<decltype(u)>::value
为真;如果是is_floating_point
,那么你也是。
Concepts是类型特征的下一个逻辑步骤:实质上是特征的reified 要求。 (参见:'Concepts Lite')