Определите пустой конструктор по умолчанию без элемента конструируемых данных по умолчанию

Рассмотрим следующий пример:

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

Решение

std::experimental::optional или эквивалент повышения имеет небольшие издержки, но имеет дело с «это может быть или не построено».

Небезопасный эквивалент будет 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);
)

Выше вызывается переданная лямбда с индексом для каждого элемента для создания элемента.

1

Другие решения

Если ThirdPartyLibraryType не имеет конструктора по умолчанию, есть вероятность, что это связано с действительным проектное решение / причина.

Тогда у вас есть два подхода:

  • либо вы найдете подходящие параметры для конструктора не по умолчанию, и вы используете их в своей оболочке;

  • или вы задерживаете строительство вашего ThirdPartyLibraryTypeДо тех пор, пока вы не знаете, какой из его конструкторов использовать и с какими параметрами.

Первый подход будет выглядеть так:

class MyWrapper {
public:
MyWrapper() : impl(/*parameters that you've selected*/) {};
private:
ThirdPartyLibraryType impl;
};

Perhap отвечает вашим потребностям, потому что вы уже знаете, какие параметры конструктора вы хотите использовать, или потому что вы можете позволить себе создание недорогого объекта и перезаписать его позже. Но это не всегда хорошая идея …

Второй подход будет использовать указатель, который вы хотели бы избежать. Этот подход имеет много преимуществ:

  • Вы можете создать огромные массивы, инициализированные по умолчанию, как в вашем примере, и перезаписать недорогие оболочки по умолчанию сгенерированными объектами.
  • Вы уважаете дизайн библиотеки, на которую вы полагаетесь, создавая только те объекты, которые имеют смысл.
  • Вы можете уменьшить зависимость от сторонней библиотеки: модулям компиляции, которым требуется ваша обертка, не нужно знать сторонний тип или включать заголовки сторонней библиотеки (предварительное объявление достаточно).

Фактически, очевидный подход с указателем заставит вашу оболочку реализовать PIMPL идиома.

1

По вопросам рекламы [email protected]