2)您能想到哪些技术原因会阻止“完美的转发构造函数”成为适当的替代方案?
我在这里展示了这种完美转发方法的一个问题:在 C++0x 中转发所有构造函数。
此外,完美的转发方法不能“转发”基类构造函数的显式性:要么它始终是转换构造函数,要么永远不会,并且基类将始终被直接初始化(始终使用所有构造函数,甚至显式那些)。
另一个问题是初始化列表构造函数,因为您无法Args
推断initializer_list<U>
. 相反,您需要使用B{args...}
(注意大括号)转发到基础并使用or或初始化D
对象。在这种情况下,将是初始值设定项列表的元素类型,并将它们转发给基类。然后初始化列表构造函数可以接收它们。这似乎会导致不必要的代码膨胀,因为模板参数包可能包含大量类型序列,用于每种不同的类型和长度组合,并且因为您必须选择初始化语法,这意味着:(a, b, c)
{1, 2, 3}
= {1, 2, 3}
Args
struct MyList {
// initializes by initializer list
MyList(std::initializer_list<Data> list);
// initializes with size copies of def
MyList(std::size_t size, Data def = Data());
};
MyList m{3, 1}; // data: [3, 1]
MyList m(3, 1); // data: [1, 1, 1]
// either you use { args ... } and support initializer lists or
// you use (args...) and won't
struct MyDerivedList : MyList {
template<class ... Args>
MyDerivedList(Args&& ... args) : MyList{ args... } { }
};
MyDerivedList m{3, 1}; // data: [3, 1]
MyDerivedList m(3, 1); // data: [3, 1] (!!)