首页 > 解决方案 > unique_ptr 参数类型的模板参数推导指南?

问题描述

是否可以编写一个演绎指南,以便Simple可以在没有模板参数的情况下声明一个实例?我已经尝试过,但无法获得正确的形式来提取std::unique_ptr元素类型。

//------------------------------------------------------------------------------
template< class T >
class Simple
{
public:
    Simple( std::unique_ptr< T >& u ) :
    u_( u )
    {}
private:
    std::unique_ptr< T >& u_;
};

class MyThing
{};

int main()
{
    std::unique_ptr< MyThing > upSimple;
    Simple( upSimple ); // error C2955: 'Simple': use of class template requires template argument list
}

标签: c++templatesc++17template-argument-deduction

解决方案


是否可以编写一个推导指南,以便可以在没有模板参数的情况下声明 Simple 的实例?我已经尝试但无法获得正确的形式来提取 std::unique_ptr 元素类型。

问题是另一个。

隐式生成的推导指南完全能够为Simple.

正如 Rakete1111 所指出的,这是一种“最令人头疼的解析”问题。

写作

Simple( upSimple );

您的意图是获取使用对象初始化的未命名临时对象的初始化类型SimpleSimple<MyThing>感谢新的 C++17 隐式生成的推导指南)upSimple

不幸的是,编译器(visual-c++,但与 g++ 和 clang++ 相同)将其解释为名称和类型的新变量的声明(注意声明 C++ 变量的括号是多余的但完全合法;int (i);您声明了一个itype的变量) .intupSimpleSimple

这给出了一个错误,因为

(1)upSimple在前一行中定义,所以我们重新声明upSimple

(2) 隐式生成的推导指南无法在没有构造函数参数的情况下推T导出Simple.

为了避免这种歧义,并获得Simple<MyThing>对象的初始化,您可以将值保存在变量中

auto s = Simple(upSimple);

或也与

Simple s(upSimple);

所以编译器不能再将该行解释为变量的声明upSimple

如果你真的想要一个未命名的临时对象,你可以使用统一初始化(你可以使用大括号代替圆括号)

//.....V..........V
Simple { upSimple };

不能解释为变量声明。

而且,是的:强制使用新的 C++17 标准(通过/std:c++17-std=c++17特定编译器所需的任何一个)也是有用的。


推荐阅读