我在c ++游乐场玩容器,遇到了技术问题。
我正在尝试为容器实现一个emplace方法。现在它应该采用一个已构造的元素并将其传递给allocator构造方法。
我最终得到了三种方法,模板emplaceA
和一对emplaceB1
,emplaceB2
。一切按预期工作。
我的问题是emplaceA
没有明确说明Arg
只能是T
(这就是我想要的)。并且emplaceB1
,emplaceB2
在两个不同的地方提供了几乎相同的实现(我将其视为缺陷)。
有解决方法吗?
template<class T, class A> class container {
public:
using allocator_traits = typename std::allocator_traits<A>;
...
template<class Arg> void emplaceA (int n, Arg&& arg){
allocator_traits::construct(allocator_, data_+n, std::forward<Arg>(arg));};
void emplaceB1(int n, const T& t){
allocator_traits::construct(allocator_, data_+n, t);};
void emplaceB2(int n, T&& t){
allocator_traits::construct(allocator_, data_+n, std::move(t));};
...
};
答案 0 :(得分:0)
要限制模板化功能,您可以使用sfinae来防止发送不需要的类型。
在以下示例中,我们将模板函数限制为仅在Arg
可转换为T
时才可调用。请注意,即使两种类型相同,is_convertible
也会起作用。
template<class Arg, std::enable_if_t<std::is_convertible<Arg, T>::value, int> = 0>
void emplaceA(int n, Arg&& arg){
// ...
}
请勿忘记添加标题<type_traits>
当然,如果您想检查发送的类型是否严格T
,您可能希望将std::is_same
与腐朽类型一起使用。
template<class Arg, std::enable_if_t<std::is_same<std::decay_t<Arg>, T>::value, int> = 0>
void emplaceA(int n, Arg&& arg){
// ...
}