我在我的 C++ Playground 上玩容器,我遇到了相当技术性的问题。
我正在尝试为容器实现一个 emplace 方法。现在它应该接受一个已经构建的元素并将其传递给分配器构造方法。
我最终得到了三种方法,模板化的 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));};
...
};
最佳答案
要限制模板化函数,您可以使用 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){
// ...
}
关于c++ - 模板化成员函数和参数转发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39453180/