我正在尝试编写一个(C ++ 98)程序,其中出现以下模式:我有一个非常简单的通用元组类,我需要使用工厂构造的值填充它。最小的示例代码如下:
#include <iostream>
class diagnostics
{
private:
int payload;
public:
diagnostics(int a)
: payload(a)
{
std::cout << "constructor\n";
}
diagnostics(const diagnostics& o)
: payload(o.payload)
{
std::cout << "copy constructor\n";
}
~diagnostics()
{
std::cout << "destructor [" << payload << "]\n";
}
};
struct creator
{
static diagnostics create()
{
static int i = 0;
return diagnostics(++i);
}
};
template<class Head, class Tail>
struct tuple
{
Head head;
Tail tail;
typedef Head head_t;
typedef Tail tail_t;
tuple(const Head& h, const Tail& t)
: head(h), tail(t)
{
}
};
struct empty_tuple { };
template<class Tuple, class Create>
struct create_helper
{
static Tuple create()
{
return Tuple(Create::create(),
create_helper<typename Tuple::tail_t, Create>::create());
}
};
template<class Create>
struct create_helper<empty_tuple, Create>
{
static empty_tuple create()
{
return empty_tuple();
}
};
template<class Tuple, class Create>
Tuple create()
{
//return Tuple(Create::create(), empty_tuple()); //(*)
return create_helper<Tuple, Create>::create();
}
int main()
{
typedef tuple<diagnostics, empty_tuple> tuple_t;
tuple_t a = create<tuple_t, creator>();
}
输出
constructor
copy constructor
destructor [1]
destructor [1]
我想摆脱中间两行。
为了简化讨论,我们可以在上面的代码中取消注释标记为(*)的行;这将打破泛因,但不会打破程序。
现在我的主要问题是:我该如何解决这个问题?标准是否阻止了RVO(可能是RVO必须在这里递归完成)?如果没有,接受编译器不够好,有没有办法让我以明确的方式发生这种情况?我很好地使create()的调用复杂化,但我不想让元组中的对象复杂化(特别是,其中一些不能默认构造,我不想引入额外的“unitialized”陈述给他们)。可以安抚新的帮助吗?
以下问题似乎有关,但最终没有帮助:Why does not RVO happen here?)
答案 0 :(得分:2)
五分钟后回答我自己的问题我觉得有点愚蠢,但这似乎是获取以下信息的最合适方式:
这是一个解决方案。我们可以将创建代码传递给元组类本身:
struct FILLIT { };
template<class Head, class Tail>
struct tuple
{
Head head;
Tail tail;
typedef Head head_t;
typedef Tail tail_t;
tuple(const Head& h, const Tail& t)
: head(h), tail(t)
{
}
tuple(const tuple& o)
: head(o.head), tail(o.tail)
{
std::cout << "tuple copy\n";
}
template<class Create>
tuple(FILLIT, Create c)
: head(Create::create()), tail(FILLIT(), c)
{
}
};
struct empty_tuple
{
empty_tuple() {};
template<class C>
empty_tuple(FILLIT, C) {};
};
create的兼容实现是
template<class Tuple, class Create>
Tuple create()
{
return Tuple(FILLIT(), Create());
}
我仍然对其他方法感兴趣。