功能中的模板模板替换

时间:2015-04-15 16:10:49

标签: c++ templates

我正在实现自己的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()函数以便编译?

5 个答案:

答案 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一起使用 但我不知道如何验证基本模板类