gpt4 book ai didi

c++ - 同类容器、派生类、初始化列表和移动语义

转载 作者:太空宇宙 更新时间:2023-11-04 11:51:30 25 4
gpt4 key购买 nike

我的代码使用了一些卑鄙的技巧,使其看起来像我认为一个不错的界面。最重要的类 Worker 旨在让调用者使用临时对象构造它;然后构造函数将接受它们。我认为代码是不言自明的:

#include <iostream>
#include <vector>
#include <memory>

using namespace std;

struct Base
{
virtual void
print
( void )
{
cout << "Base" << endl;
};
};

struct Derived1 : public Base
{
virtual void
print
( void )
{
cout << "Derived1" << endl;
};
};

struct Derived2 : public Base
{
virtual void
print
( void )
{
cout << "Derived2" << endl;
};
};

class Worker
{
private:
/* Arrays can't hold references, and
* vectors are homogenous, so the
* only option is to use (smart) pointers. */
vector< unique_ptr<Base> >
V
;

/* The dirty trick I spoke about. */
template<typename T> void
init
( T && t )
{
V.emplace_back( new T( forward<T>(t) ) );
return;
};
template<typename T , typename ... U> void
init
( T && t , U && ... u )
{
V.emplace_back( new T( forward<T>(t) ) );
/* The usage of std::move() is explained below. */
init(move(u)...);
return;
};

public:
template<typename ... T>
Worker
( T && ... t )
{
/* Use std::move() because, inside the body
* of the function, the arguments are lvalues.
* If I hadn't put std::move(), the compiler
* would complain about an attempt of using
* _new_ with a reference type (above). */
init(move(t)...);
return;
};

void
work
( void )
{
for ( const auto & x : V )
x->print();
return;
};
};

int
main
( void )
{
/* The goal: be able to create an instance of Worker
* passing temporaries to the constructor. No initializer_list
* is involved, no copies are made; clean, fast moves. */
Worker worker{ Derived1() , Base() , Derived2() };
/* This should print "Derived1\nBase\nDerived2\n". */
worker.work();

return 0;
}

尽管它编译良好 (g++ 4.8.1) 并且开箱即用,但我觉得这不是实现我的目标的最佳方式,我想摆脱那种烦人的感觉。有没有人为此找到另一种解决方法?有没有更好的方法,我的设计有什么缺点吗?

提前致谢。代码应该可以很好地编译,并显示我希望如何设计我的界面以及我为什么使用这些“技巧”。此致,卡里什

最佳答案

虽然我仍然认为这个问题更好地属于Code Review ,这是您的“肮脏把戏”的替代版本

    template < typename T >
int emplace_back(T&& t)
{
V.emplace_back( std::forward<T>(t) );
return 0;
}

template<typename ... T>
Worker
( T && ... t )
{
auto i = {emplace_back(new T{forward<T>(t)})...};
};

或者,如果您想删除该成员函数:

public:
template<typename ... T>
Worker
( T && ... t )
{
using up = std::unique_ptr<Base>;
auto f = [&](up&& p)
{ V.emplace_back(std::move(p)); return 0; };

auto i = {f( up{new T{forward<T>(t)}} )...};
};

不过,您可能会收到警告,因为 i 未被使用。此变量只需要构建一个初始化列表,其中允许包扩展。


通常,我建议使用初始化列表而不是可变参数模板 ctor(这就是它们的用途),但它们不支持移出元素,因为它们不拥有自己的存储空间。

如果您想在 ctor 的 mem-initializer-list 中初始化 vector(通过上述替代方案中的包扩展),则会出现同样的问题。

关于c++ - 同类容器、派生类、初始化列表和移动语义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18020773/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com