我试图为我的轻量级数组类实现一个std::initializer_list
构造函数,但是我立即发现一个问题,即std::initializer_list
是一个 constexpr
。我确实通过使用可变参数模板构造函数和辅助函数以某种方式解决了它,但对于这个单一目的来说,它感觉有点矫枉过正(IMO)。我使用 C++ 的经验很短,所以我相信有更好、更简单的方法。
我还考虑过使用来自 std::array
的移动构造函数?但是移动表达式的概念对我来说仍然不清楚。无论如何,这也值得考虑吗?
任何好的解决方案或建议都会对我有所帮助。
template<typename T>
class Array:private boost::scoped_array<T>{
private:
int m_length;
int CountArguments(){
return 0;
}
template<typename... Ts>
int CountArguments(T const& t,Ts const&... ts){
return 1+CountArguments(ts...);
}
void FillFromArguments(T* p){}
template<typename... Ts>
void FillFromArguments(T* p,T const& t,Ts const&... ts){
*p++=t;
FillFromArguments(p,ts...);
}
public:
Array(){}
Array(int length):
boost::scoped_array<T>(new T[length]),
m_length(length){}
template<typename... Ts>
Array(T const& t,Ts const&... ts){
m_length=CountArguments(t,ts...);
boost::scoped_array<T>::reset(new T[m_length]);
FillFromArguments(boost::scoped_array<T>::get(),t,ts...);
}
/* ... */
};
最佳答案
关于问题的评论,我没有看到 std::initializer_list
的问题。但是您绝对不需要您编写的任何成员函数。我们可以在构造函数中构造完整的数组:
template <typename... Ts,
typename = std::enable_if_t<
all_true<std::is_constructible<T, Ts&&>::value...>::value
>>
Array(Ts&&... ts)
: boost::scoped_array<T>{new T[sizeof...(Ts)]{
std::forward<Ts>(ts)...
}}
, length(sizeof...(Ts))
{
}
all_true
来自 Columbo here .这具有使用非默认可构造类型的额外好处:
struct X {
X(int ) { }
};
int main() {
Array<X> t(1, 2, 3); // OK
}
虽然更简单的解决方案是:
template <typename T>
class Array : private std::vector<T>
{
public:
// constructor
using std::vector<T>::vector;
// accessors
using std::vector<T>::size;
using std::vector<T>::begin;
using std::vector<T>::end;
using std::vector<T>::operator[];
// other functions that don't include push_back(), erase(), emplace(), ...
};
让标准库处理一切。
关于c++ - 如何实现非 constexpr `std::initializer_list` 样式构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30425538/