我正在实现自己的UniquePtr
,我想测试它与std::unique_ptr
具有相同的界面。所以我写了一个函数:
class A
{
A() { }
~A() { }
};
class B
{
B() { }
~B() { }
};
template <template <typename Type> class UPtr>
void test_unique_ptr_interface()
{
UPtr<A> p1(new A);
{
UPtr<A> p2(std::move(p1));
p1 = std::move(p2);
}
UPtr<B> p1(new B);
{
UPtr<B> p2(std::move(p1));
p1 = std::move(p2);
}
...
}
然后我想这样称呼它:
test_unique_ptr_interface<std::unique_ptr>();
test_unique_ptr_interface<UniquePtr>();
第一次调用测试std::unique_ptr
通过了测试,因此我正在测试正确的接口。第二个调用测试我自己的UniquePtr
实现作为替代品。函数test_unique_ptr_interface
会更长,我刚发布了一个简单的例子。
然而,我收到错误:
error: no matching function for call to ‘test_unique_ptr_interface()’
test_unique_ptr_interface<std::unique_ptr>();
我应该如何声明test_unique_ptr_interface()
函数以便编译?
答案 0 :(得分:5)
查找declaration of std::unique_ptr
:
template <class T, class Deleter = std::default_delete<T>>
class unique_ptr;
这是一个包含2个模板参数的类模板。要完全复制它,您必须更改您的类模板以匹配,并更改测试功能:
template <template <typename, typename> class UPtr>
void test_unique_ptr_interface()
{
// ...
}
另一种方法是将模板模板参数变为variadic:
template <template <typename... > class UPtr>
void test_unique_ptr_interface()
{
// ...
}
这将允许您的类只保留一个模板参数。请注意,它不会是std::unique_ptr
的完全替代品。
答案 1 :(得分:3)
将模板参数列表更改为:
template<template<class...>class UPtr>
由于std::unique_ptr
有2个参数,template<class>class
不匹配。
如何在C ++中匹配模板有点奇怪(而且我不知道它的理由),但template<class...>class
将匹配任何带有零值参数的template class
(即,只输入参数)。
std::unique_ptr<?>
(其中2个参数,其中1个默认)和UniquePtr<?>
(取1个参数)都匹配。传递一个参数将导致std::unique_ptr
使用其默认的第二个参数。
令人讨厌的是template
带有2个参数,第二个是默认的,不会匹配template<class>class
,但这是“#34;奇怪的&#34;”的一部分。方式模板模板参数匹配。你可以写一个适配器:
template<class T>using unique_ptr1 = std::unique_ptr<T>;
并将unique_ptr1
直接传递给您的test_unique_ptr_interface
。
可替换地:
template<template<class...>class Z>
struct unary_version {
template<class T>
using apply = Z<T>;
};
然后
test_unique_ptr_interface< unary_version<std::unique_ptr>::template apply >
是另一种不改变test_unique_ptr_interface
的方法。但正确的答案是替换test_unique_ptr_interface
。
请注意,您缺少删除功能意味着您不能与unique_ptr
界面匹配。您可以使用这些功能来扩充您的课程。您可以将现有功能重命名为test_unique_ptr_interface_with_one_arg
,并从同时测试删除功能的test_unique_ptr_interface
中调用它。
答案 2 :(得分:1)
@Angew给出了正确答案,但根据他的具体建议,我需要将UPtr<A> p1(new A);
更改为UPtr<A, std::default_delete<A>> p1(new A);
。为避免这种情况,我需要从
template <template <typename Type> class UPtr>
void test_unique_ptr_interface()
到
template <template <typename T, typename Deleter=std::default_delete<T>> class UPtr>
void test_unique_ptr_interface()
然后在函数体中不需要进一步的更改,我仍然可以使用UPtr<A> p1(new A);
并且所有内容都会编译。
答案 3 :(得分:0)
std::unique_ptr
需要两个模板参数(类型和删除器),因此您的模板模板也需要采用相同的两个参数。
答案 4 :(得分:-3)
仅限使用(无需template <typename Type>
)
template <class UPtr>
对于测试,您可以将std :: is_base_of与static_assert一起使用 但我不知道如何验证基本模板类