如何在 Visual Studio 中解决 make_shared 的 10 个限制
Posted
技术标签:
【中文标题】如何在 Visual Studio 中解决 make_shared 的 10 个限制【英文标题】:How to work around 10 limit for make_shared in Visual Studio 【发布时间】:2013-01-15 17:12:48 【问题描述】:在一些旧代码上使用 C++10 的新功能时,我遇到了一个问题,即我无法调用需要 12 个参数的make_shared
。我记得微软的 STL 谈到他们如何使用模拟 make_shared
并且最多 10 个。
显然,仅仅为此重构代码是不可能的,所以基本上我的问题是 - 有没有办法在 VS 2010 中获得超过 10 个参数到 make_shared
。
【问题讨论】:
尝试将/D_VARIADIC_MAX=12
添加到编译器选项中。我记得读过你只能将它增加到 10,但值得一试。
@Praetorian blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx 说限制是 5 到 10(含)。
"显然,仅仅为了这个而重构代码是不可能的" 重构代码怎么样,因为有 10 个参数的构造函数显然在乞求重构?
@NicolBolas 实际上没有。我不想泄露专家的商业机密(写 12 arg ctor 类的大师:D),但相信我,它不是一个普通的类,更像是一个味精。 :D
【参考方案1】:
make_shared<foobar>(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
可以替换为
shared_ptr<foobar>(new foobar(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12));
在 C++11 中,std::make_shared 实际上是对使用第二种方法创建对象的性能优化,因为它只执行一次内存分配而不是两次,但是一旦超过 10 个变量,你就不会有很多选择。
【讨论】:
Doh,我太愚蠢了... shared_ptrmake_shared
对于编写异常安全的代码也很有用。如果您使用这种方式,请给每个 shared_ptr
一个名称,不要将它们作为临时对象传递。【参考方案2】:
如果您真的想使用make_shared
的效率优势,那么您仍然可以这样做:
#include <tuple>
#include <memory>
#include <redi/index_tuple.h>
template<typename X, typename... Args>
std::shared_ptr<X>
make_shared_TO_THE_MAX(Args&&... args)
struct Wrapper
X x;
template<typename... T>
Wrapper(std::tuple<T...> targs) : Wrapper(targs, to_index_tuple<T...>)
template<typename T, unsigned... I>
Wrapper(T targs, index_tuple<I...>) : x(std::get<I>(targs))
;
auto wrapped = std::make_shared<Wrapper>(std::forward_as_tuple(std::forward<Args>(args)...));
return std::shared_ptr<X>(wrapped, &wrapped->x);
这会将构造函数参数捆绑成一个引用元组并将其传递给make_shared
,因此make_shared
不能处理10 个参数并不重要,因为它只能得到一个。而不是make_shared<X>
,它使用make_shared<Wrapper>
,它将为Wrapper
(其大小和布局与其X
类型的成员相同)分配空间,并使用参数元组构造它。 Wrapper
构造函数委托给另一个构造函数,该构造函数扩展元组以传递给 X
构造函数。
最后,它使用shared_ptr
别名构造函数返回与shared_ptr<Wrapper>
共享所有权但存储X
对象的地址的shared_ptr<X>
。
<redi/index_tuple.h>
是 my own header,但我正在尝试使 something similar 标准化为 C++14。
这也可以在没有可变参数模板的情况下完成,但工作量更大。这里是两个参数,十二个再加十个!
#include <tuple>
#include <memory>
template<typename X, typename Arg0, typename Arg1>
std::shared_ptr<X>
make_shared_TO_THE_MAX(Arg0&& arg0, Arg1&& arg1)
struct Wrapper
X x;
template<typename T0, typename T1>
Wrapper(std::tuple<T0, T1> targs)
: x(std::get<0>(targs), std::get<1>(targs))
;
auto wrapped = std::make_shared<Wrapper>(std::forward_as_tuple(std::forward<Arg0>(arg0), std::forward<Arg1>(arg1)));
return std::shared_ptr<X>(wrapped, &wrapped->x);
【讨论】:
等等,不是... var 模板吗?如果是这样,那么:(因为:“有没有办法在 VS 2010 中获得超过 10 个参数来 make_shared。” 它不会将超过 10 个参数传递给make_shared
,这就是重点。但它确实使用了可变参数。我在想编译器支持可变参数但 stdlib 不支持,但我认为这仅适用于最新的编译器更新。您仍然可以在没有可变参数的情况下完成上述技巧,只需手动列出您的类型需要的 12 个参数,然后使用 std::get<0>(t), std::get<1>(t), std::get<2>(t),
等显式解包元组。如果 tuple
也有十个限制,您需要传递两个元组。 以上是关于如何在 Visual Studio 中解决 make_shared 的 10 个限制的主要内容,如果未能解决你的问题,请参考以下文章
visual studio乱码怎么办 vs繁体中文乱码问题解决方法
如何强制在 Visual Studio 2013 中打开解决方案文件 (SLN)?
启动visual studio 2008后显示对话框: visual studio的试用版评估期已结束。 如何解决。