考虑以下示例:
class MyWrapper {
public:
MyWrapper() {};
private:
ThirdPartyLibraryType impl;
};
假设ThirdPartyLibraryType
没有默认构造函数,我无法帮助它,因为它是第三方库类型。然后,此代码将无法编译,因为默认构造函数MyWrapper()
必须调用ThirdPartyLibraryType
的默认构造函数。现在我只希望默认构造函数不执行任何操作,因为我使用默认构造函数的用例如下:
std::array<MyWrapper,10> myArray;
for (int i=0;i<10;++i) {
myArray[i] = generateMyWrapper(...);
}
有没有办法强制生成默认构造函数? (没有开销,我不想使用ThirdPartyLibraryType*
有数据成员的明显解决方案)
修改 到目前为止,我使用的方法类似于Yakk提出的方法,它不依赖于默认构造函数,但我认为成员函数调用的情况很难看:
template<class T, size_t N, class C, class CF>
std::array<T,N> gen_array(C const& obj, CF&& f) {
...
use obj.f
...
}
class MyClass {
MyWrapper generateMyWrapper(int i) const { ... }
auto genMyWrapperTypeArray() const {
return
gen_array<
MyWrapper,10,MyClass,
MyWrapper(MyClass::*)(int) const
> (
*this, &MyClass::generateMyWrapper
);
}
}
我还没有对它进行测试,我的观点是,如果语法不完全相同,它仍然比我在默认构造函数可用时使用的简单for循环复杂得多。
答案 0 :(得分:1)
std::experimental::optional
或提升等价物有适度的开销,但可以处理eith&#34;这可能是或不构建&#34;。
不安全的等效物是std::aligned_storage_t
你在哪里施工。问题是破坏,你需要知道它是否构建。
更好的选择可能是选择整个数组,而根本没有零参数ctor。打包构建每个参数所需的内容并创建一个构造函数,而不是循环。
template<class T, size_t...Is, class F>
std::array<T,sizeof...(Is)> gen_array(
std::index_sequence<Is...>, F&&f
){
return {{f(Is)...}};
)
template<class T, size_t N, class F>
std::array<T,N> gen_array(
F&&f
){
return gen_array(std::make_index_sequence<N>{}, f);
)
上面调用传递的lambda和每个元素的索引来构造元素。
答案 1 :(得分:1)
如果ThirdPartyLibraryType
没有默认构造函数,则可能是由于有效的设计决策 / reason。
然后你有两种方法:
要么为非默认构造函数找到一些合适的参数,要在包装器中使用它们;
或者您推迟构建ThirdPartyLibraryType
,直到您知道要使用哪个构造函数以及使用哪些参数。
第一种方法如下:
class MyWrapper {
public:
MyWrapper() : impl(/*parameters that you've selected*/) {};
private:
ThirdPartyLibraryType impl;
};
Perhap它适合您的需求,因为您已经知道要使用哪些构造函数参数,或者因为您可以负担得起构建廉价对象并在以后覆盖它。但这并不总是一个好主意......
第二种方法是使用您想要避免的指针。这种方法有许多优点:
事实上,明显的指针方法会使你的包装器实现SO answer。