在构造期间使用std::tuple成员引用
Use std::tuple member references during construction?
#include "MassivePOD.h"
#include "DependantClass.h" // Constructor: `DependantClass(MassivePOD&)`
class ExplicitSolution
{
public:
ExplicitSolution() : m_pod{...}, m_dep{m_pod} { };
private:
MassivePOD m_pod;
DependantClass m_dep;
};
template<typename... T>
class TemplatedSolution
{
public:
template<typename... TupArgs> TemplatedSolution(TupArgs...);
private:
// Can assume in-order construction works
std::tuple<T...> m_tuple;
};
int main()
{
ExplicitSolution a{}; // Easy!
TemplatedSolution<MassivePOD, DependantClass> b{
std::forward_as_tuple(...) // Forwarded to MassivePOD constructor
, std::forward_as_tuple(???) // Forwarded to DependantClass constructor
}; // Hard?
}
我希望这个例子能说明我的问题。在构建整个std::tuple
之前,我想引用之前构建的std::tuple
成员。是否有一个优雅的解决方案?我知道这是可能的使用void *
黑客,但我宁愿寻求一些帮助之前走上黑暗孤独的道路。
<标题>想法一h1> 试过做一个get_ref
函数,但我得到了同样的问题,我无法访问尚未创建的对象的成员函数。这是我的一个尝试。
#include <tuple>
#include <utility>
class Foo // simplified base-case
{
public:
constexpr Foo(int x, char y, int& z) : m_tup{x, y, z*5.0} { };
constexpr int& get_int() { return std::get<0>(m_tup); };
constexpr char& get_char() { return std::get<1>(m_tup); };
constexpr double& get_double() { return std::get<2>(m_tup); };
private:
std::tuple<int, char, double> m_tup;
};
int main()
{
auto super = Foo(5, 'a', ::get_int()); // ???
}
演示<标题>想法二然后我想也许我可以做一些像std::function
对std::place_holders
所做的事情,所以一个静态对象包含一个指针/引用,指向std::tuple
的每个元素的位置。我认为这是值得尝试的,但我不知道如何在实践中实现它…
另一个建议:元组类不接受成员构造函数的形参,而是接受接收正在构造的实例并返回成员的函数。然后,这些函数可以通过getter来引用前面构造的成员。您所要做的就是确保早期成员的getter工作,并且在构造后期成员时不会调用未定义的行为。
下面是两个元素的硬编码示例,以演示该原则。我将把它留给你,让它与n
元素一起工作。注意,本质上你将在这里重新实现一个元组——我不确定你是否可以用现有的std::tuple
来做这件事。
template<typename A, typename B>
class TemplatedSolution
{
public:
template<typename AF, typename BF> TemplatedSolution(AF af, BF bf)
: a(af(*this))
, b(bf(*this))
{
}
A& get_first() {
return a;
}
B& get_second() {
return b;
}
private:
A a;
B b;
};
用法:
typedef TemplatedSolution<MassivePOD, DependantClass> ClassT;
ClassT b{
[](ClassT& res) { return MassivePOD(); },
[](ClassT& res) { return DependantClass(res.get_first()); },
};
由于返回值优化,MassivePOD
s将直接在TemplatedSolution
实例中构造。
这里有一个完整的示例,说明没有副本。
如何使用std::shared_ptr
并将其存储为TupleWrapper
中的std::shared_ptr
?
auto p_first_member_tmp = std::make_shared<MassivePOD>(
std::forward_as_tuple(...));
TupleWrapper<std::shared_ptr<MassivePOD>, DependantClass> wrapper{
p_first_member_tmp,
std::forward_as_tuple(*p_first_member_tmp, ...)}
这是一个额外的间接级别,但至少不会复制或移动昂贵的复制或移动结构。
我在考虑为什么在Python这样的语言中这从来都不是一个问题,这是因为对象只被创建一次,然后其他所有东西都指向它——这与这里的方法近似。您也不需要对对象的生命周期进行任何额外的跟踪,因为shared_ptr
已经为您完成了。
相关文章:
- 在 std::tuple 上使用 std::variant 的问题
- 在构造函数中使用可变参数初始化 std::tuple
- 转发复制的 std::tuple
- 我可以将新的 std::tuple 放入内存映射区域,并在以后读回吗?
- std::tuple 可以根据其值在编译时/运行时排序吗?
- 返回 std::tuple 中的引用和值
- 带有引用的std::tuple在clang中编译失败,但在gcc中编译失败
- 尝试实现std::tie和std::tuple的小版本
- std::tuple默认构造函数,带有move可构造元素
- 来自带有 std::tuple 的地图
- 如何从 std::async 任务返回 std::tuple
- 为什么 std::when_any 使用 std::tuple 而不是 std::vector 作为其结果类型?
- 为什么 std::integral_constant 在爆炸 std::tuple 时是必需的?
- 如何在std :: tuple中的每个元素上应用constexpr函数
- 如果创建支持返回可变参数类型列表的通用模板 API,我应该使用 std::tuple 还是其他东西?
- 类型安全 - all_of/ any_of/ none_of for std::tuple
- 将__m128i值转换为 std::tuple
- 使结构的行为类似于 std::tuple
- std::tuple faster than std::array?
- C++ 在标准::unordered_map中设置 std::tuple 值