【问题标题】:make_unique does not compilemake_unique 不编译
【发布时间】:2012-12-02 18:11:50
【问题描述】:

我正在尝试为std::unique_ptr 创建和使用make_unique,就像std::make_shared 存在于std::shared_ptr described here 一样。 Herb Sutter mentions make_unique 的可能实现如下所示:

template<typename T, typename ...Args>
std::unique_ptr<T> make_unique( Args&& ...args )
{
    return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) );
}

这似乎对我不起作用。我正在使用以下示例程序:

// testproject.cpp : Defines the entry point for the console application.
#include "stdafx.h"

#include <iostream>
#include <memory>
#include <utility>

struct A {
  A(int&& n) { std::cout << "rvalue overload, n=" << n << "\n"; }
  A(int& n)  { std::cout << "lvalue overload, n=" << n << "\n"; }
};

template<typename T, typename ...Args>
std::unique_ptr<T> make_unique( Args&& ...args ) {
  return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) );
}

int main() {
  std::unique_ptr<A> p1 = make_unique<A>(2); // rvalue
  int i = 1;
  std::unique_ptr<A> p2 = make_unique<A>(i); // lvalue
}

编译器(我使用的是 VS2010)给了我以下输出:

1>d:\projects\testproject\testproject\testproject.cpp(15): error C2143: syntax error : missing ',' before '...'
1>d:\projects\testproject\testproject\testproject.cpp(16): error C2065: 'Args' : undeclared identifier
1>d:\projects\testproject\testproject\testproject.cpp(16): error C2988: unrecognizable template declaration/definition
1>d:\projects\testproject\testproject\testproject.cpp(16): error C2059: syntax error : '...'
1>d:\projects\testproject\testproject\testproject.cpp(22): error C2143: syntax error : missing ';' before '{'
1>d:\projects\testproject\testproject\testproject.cpp(22): error C2447: '{' : missing function header (old-style formal list?)

另外,如果您将 make_unique 实现替换为以下内容

template<class T, class U>
std::unique_ptr<T> make_unique(U&& u) {
  return std::unique_ptr<T>(new T(std::forward<U>(u)));
}

(取自this 示例),它可以编译并正常工作。

谁能告诉我有什么问题?在我看来,VS2010 在模板声明中 ... 出现了一些问题,我不知道该怎么办。

【问题讨论】:

  • 自 CTP 起才支持可变参数模板。
  • 您应该注意 Herb Sutter 的建议不适用于数组类型。 Stephan T Lavavej 在他最近一集中的 Core C++ 中发布了一个改进版本,它也适用于数组,例如 make_unique&lt;int[]&gt;(1, 2, 3)
  • 如果您想在 Visual Studio 中使用可变参数模板,您需要最新的更新。我自己的指示:scrupulousabstractions.tumblr.com/post/36204698243/…
  • 您的 make_unique 示例无法为我编译。我得到error C2248: 'std::unique_ptr&lt;_Ty&gt;::unique_ptr' : cannot access private member declared in class 'std::unique_ptr&lt;_Ty&gt;'

标签: c++ visual-studio-2010 visual-c++ c++11 variadic-templates


【解决方案1】:

可变参数模板在 Visual C++ 11 的已发布版本中不可用。但是,您可以使用大量复制/粘贴代码来模拟参数扩展,以获取不同数量的参数,或者使用 Microsoft 中使用的相同编译器技巧自己实现“伪变量”。来自 Herb Sutter 博客的评论:http://herbsutter.com/gotw/_102/#comment-6428

#include <memory> // brings in TEMPLATE macros.

#define _MAKE_UNIQUE(TEMPLATE_LIST, PADDING_LIST, LIST, COMMA, X1, X2, X3, X4)  \
\
template<class T COMMA LIST(_CLASS_TYPE)>    \
inline std::unique_ptr<T> make_unique(LIST(_TYPE_REFREF_ARG))    \
{    \
    return std::unique_ptr<T>(new T(LIST(_FORWARD_ARG)));    \
}

_VARIADIC_EXPAND_0X(_MAKE_UNIQUE, , , , )
#undef _MAKE_UNIQUE

【讨论】:

  • 注意:_[A-Z].* 标识符的使用保留给实现(在您的情况下,VC++ 编译器和 Dirkumware STL)。
  • @MatthieuM。感谢您指出这一点,我个人不喜欢以_ 开头的标识符。当我在工作中实现 make_unique() 时,我手动将代码扩展为 10 个参数(错误、复制/粘贴)并将其转储到实用程序命名空间中以避免与未来的 std 实现冲突。
【解决方案2】:

根据MSDN,Visual C++ 2010 或 2012 不支持可变参数模板。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-14
  • 2019-07-20
  • 1970-01-01
  • 2014-08-27
  • 2015-01-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多