正如@KerrekSB 提到的,最简单的方法是将foo
's 的构造函数复制到bar
:
bar(int a, int b) : f(a, b) {}
foo
然而,当有大量构造函数时,这很快就会变得不切实际,甚至可能是不可能的 if bar
is atemplate<typename T>
并且您想为任何可能的T
.
进入 C++11 的完美转发:
template<typename... Args>
bar(Args&&... args) : f(std::forward<Args>(args)...) {}
这允许您的bar
构造函数将其接收到的任何参数直接转发给foo
构造函数,就像emplace
C++11 标准库中的方法一样。
现在还有一个问题:因为你的bar
构造函数接受你的构造函数接受的任何参数foo
,显然如果foo
有一个复制构造函数,那么bar
将接受它:
bar b1(1, 2); // ok
foo f(1, 2);
bar b2(f); // ok too!
诀窍是删除相关的构造函数:
struct bar {
foo f;
template<typename... Args>
bar(Args&&... args) : f(std::forward<Args>(args)...) {}
bar(const foo&) = delete;
bar(foo&) = delete;
};
foo f(1, 2);
bar b2(f); // error: use of deleted function ‘bar::bar(foo&)’
请注意,我故意没有删除移动构造函数,因为我假设您禁用复制的动机是性能。这样你仍然可以写:
foo f(1, 2);
bar b1(std::move(f)); // move: ok
bar b2(foo(1, 2)); // temporary: ok (it is really moved)
当然,如果您也想删除移动构造函数,这非常简单:
struct bar {
foo f;
template<typename... Args>
bar(Args&&... args) : f(std::forward<Args>(args)...) {}
bar(const foo&) = delete;
bar(foo&) = delete;
bar(foo&&) = delete;
};
foo f(1, 2);
bar b1(std::move(f)); // error: use of deleted function ‘bar::bar(foo&&)’
bar b2(foo(1, 2)); // error: use of deleted function ‘bar::bar(foo&&)’
特质:我不知道为什么,但即使在 中删除了移动构造函数bar
,它仍然接受默认构造的临时构造(GCC 4.7):
bar b3(foo()); // WTH, this works
我错过了一定有一个很好的理由,但我不知道这里到底发生了什么。如果有人可以对此有所了解...