【问题标题】:Why can't I use std::unique_ptr as a "template<class> class" argument?为什么我不能使用 std::unique_ptr 作为“template<class> class”参数?
【发布时间】:2018-07-16 08:35:45
【问题描述】:

这段代码:

#include <memory>

template <template <typename> class Ptr>
class A { Ptr<int> ints; };

using B = A<std::unique_ptr>;

产生以下错误(使用 GCC 6.3):

a.cpp:6:28: error: type/value mismatch at argument 1 in template parameter list for ‘template<template<class> class Ptr> class A’
 using B = A<std::unique_ptr>;
                            ^
a.cpp:6:28: note:   expected a template of type ‘template<class> class Ptr’, got ‘template<class _Tp, class _Dp> class std::unique_ptr’

现在,我可以像这样解决这个问题:

template <typename T>
using plugged_unique_ptr = std::unique_ptr<T>;
using B = A<plugged_unique_ptr>;

但为什么我必须这样做?我的意思是,为什么编译器不愿意将std::unique_ptr 的第二个模板参数“插入”其默认值并允许将std::unique_ptr 用作A 的模板参数?

【问题讨论】:

  • 注意它应该从C++17开始编译。
  • @HolyBlackCat 你能告诉我为什么 C++17 能做到这一点吗?
  • @rubenvb This page 有一些解释。
  • @HolyBlackCat 我猜你的意思是该页面上的这一点:“要将模板模板参数A匹配到模板模板参数P,A的每个模板参数都必须匹配相应的模板P 的参数精确(C++17 前)P 必须至少与 A 一样特化(C++17 起)"

标签: c++ c++11 unique-ptr template-argument-deduction template-templates


【解决方案1】:

因为模板模板参数需要完全匹配。这意味着默认模板参数在这里不相关。请注意,将模板模板参数扩展为两个模板参数只是偶然:允许实现添加比标准定义的模板参数更多的模板参数,并且在标准容器周围的 SFINAE 的情况下通常会这样做。

这也是我通常建议不要使用任何模板模板参数的主要原因,而是只使用普通模板类型名。如果您需要访问嵌套模板类型,请提供内部访问器,例如value_type 或外部访问器(例如 tuple_element)在模板内访问这些。


注意:这显然在 C++17 中发生了变化,匹配不再精确,但稍微放松但更复杂。尽管如此,我仍然建议不要使用模板模板参数。

【讨论】:

  • 有时你需要它们,如果你想应用多个内部模板参数。
  • @einpoklum 我确定有时您需要它们,但我不确定“应用多个内部模板参数”是什么意思。你能举个例子吗?
  • template &lt;template &lt;typename&gt; class Ptr&gt; struct buffers_t { Ptr&lt;foo[]&gt; foos; Ptr&lt;bar[]&gt; bars; Ptr&lt;baz[]&gt; bazes; }
  • @einpoklum 显而易见的事情是如何让你忽略的。感谢您抽出宝贵时间:)。
【解决方案2】:

std::unique_ptr 有第二个模板参数,默认为 template &lt;typename&gt; class Ptrstd::unique_ptr 不匹配

template &lt;typename...&gt; class Ptr 可以工作

cppreference

【讨论】:

  • 没有完全回答我的问题,但这是一个聪明的解决方法,所以 +1!
  • 我很想template&lt;template&lt;typename, typename...&gt; class Ptr&gt; 明确说明预期参数的数量
【解决方案3】:

正如@HolyBlackCat 建议的那样,我们不再需要对 C++17 和 OP 的代码 does indeed compile (coliru.com) 使用任何解决方法。

GCC 6.3.0 默认编译 C++14 代码,不应用此语言语义更改。

【讨论】:

    猜你喜欢
    • 2020-07-01
    • 1970-01-01
    • 2011-07-16
    • 1970-01-01
    • 1970-01-01
    • 2015-04-22
    • 1970-01-01
    • 2018-09-14
    • 2016-05-12
    相关资源
    最近更新 更多