【问题标题】:Template deduction syntactical differences模板推演句法差异
【发布时间】:2020-02-13 05:42:02
【问题描述】:

我写了一个二叉树的基本程序如下

#include <iostream>
#include <memory>

template<typename T>
using sp = std::unique_ptr<T>;

template<typename T>
struct Node{
    Node(T val):
      x(val){
    }

    const sp<Node>& addL(T val){
        left = std::make_unique<Node>(val);
        return left;
    }

    const sp<Node>& addR(T val){
        right = std::make_unique<Node>(val);
        return right;
    }

    private:
    T x;
    sp<Node> left;
    sp<Node> right;
};

int main(){
    auto root = std::make_unique<Node<int>>(5);
    root->addL(10)->addR(4)->addL(12);
    root->addR(14)->addL(3)->addR(15);
}

我的问题是关于这条线

auto root = std::make_unique<Node<int>>(5);

如果我删除了&lt;int&gt; 模板参数,那么编译器会抱怨模板推导失败

tree.cpp:44:41: error: no matching function for call to ‘make_unique<template<class T> struct Node>(int)’
   44 |     auto root = std::make_unique<Node>(5);
      |                                         ^
In file included from /usr/include/c++/9/memory:80,
                 from tree.cpp:2:
/usr/include/c++/9/bits/unique_ptr.h:848:5: note: candidate: ‘template<class _Tp, class ... _Args> typename std::_MakeUniq<_Tp>::__single_object std::make_unique(_Args&& ...)’
  848 |     make_unique(_Args&&... __args)
      |     ^~~~~~~~~~~
/usr/include/c++/9/bits/unique_ptr.h:848:5: note:   template argument deduction/substitution failed:

而类似的推论适用于该行

left = std::make_unique<Node>(val);

这是因为结构中的代码在编译时已经推导出了模板,因此不需要明确指定&lt;int&gt;?这是否也解释了为什么在类函数的签名中不需要sp&lt;Node&lt;T&gt;&gt;sp&lt;Node&gt; 足以让编译器推断实际类型。

附: g++ (Ubuntu 9.2.1-17ubuntu1~16.04) 9.2.1 20191102

【问题讨论】:

  • 称为注入类模板名。在您的类模板的方法内部每次出现Node 都会转换为Node&lt;T&gt;。所以你不必明确地放 T。

标签: c++ templates


【解决方案1】:

injected-class-name, 在Node&lt;T&gt;类的范围内,Node也指Node&lt;T&gt;

所以,在

left = std::make_unique<Node>(val); // Inside class scope

没有扣除,只是注入的类名,所以等价于

left = std::make_unique<Node<T>>(val); // Inside class scope

在类范围之外,Node 引用模板类。

所以

auto root = std::make_unique<Node>(5); // Invalid

make_unique 的模板参数是类型而不是模板模板参数。

所以你必须写:

auto root = std::make_unique<Node<int>>(5);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    • 2014-06-29
    相关资源
    最近更新 更多