2017-02-09 40 views
5
#include <iostream> 
#include <string> 
#include <array> 

class C { 
private: 
    std::string a; 
    std::string b; 
    std::string c; 
public: 
    C(std::string a_, std::string b_, std::string c_) : a{a_},b{b_},c{c_} {} 
    ~C(){}; 
    C(const C&) =delete; 
    C(const C&&) =delete; 
    const C& operator=(const C&) =delete; 
    const C& operator=(const C&&) =delete; 
}; 

std::array<C,2> array = {C("","",""),C("","","")}; 

int main() 
{} 

это не скомпилирует (Android Studio с NDK и clang) с ошибкой «вызов для удаленных конструкторов c». Я знаю, что могу, например, используйте std::vector и emplace_back() для создания элемента непосредственно внутри контейнера, но в моем коде я хочу использовать только контейнеры фиксированного размера и не скопируемые/перемещаемые объекты для оптимизации. Мне, вероятно, не хватает базового элемента здесь, но нет ли способа инициализировать std::array, не создав сначала отдельные элементы, а затем скопировав их там?инициализировать std :: массив без копирования/перемещения элементов

+2

Кстати, вам не нужно ставить эти подчеркивания в именах параметров. 'C (std :: string a, std :: string b, std :: string c): a {a}, b {b}, c {c} {}' не имеет проблем с двусмысленностью и делает то, что вы ожидаете. – nwp

ответ

6

Вы можете использовать фигурные скобки заключены инициализаторы вместо временных c объектов:

std::array<c,2> array = {{{"",""},{"",""}}}; 

или

std::array<c,2> array{{{"",""},{"",""}}}; 
+0

Является ли это переносным решением? Я имею в виду, что это зависит от того, как реализуется std :: array, он должен содержать ровно один элемент типа 'T [N]'. – marcinj

+0

@marcinj Я в этом уверен. В прошлый раз, когда я проверял требование, не было того, что 'std :: array' содержит ровно один элемент типа' T [N] ', но он ведет себя так, как если бы он это делал. Существовал целый вопрос о том, можно ли опустить средний '{}', т. Е. Должно ли оно также быть допустимым: '{{" "," "}, {" "," "}}'. Последнее может измениться после C++ 11. – juanchopanza

+0

Я спрашиваю, потому что я читал один SO, где T.C. сказал, что это не гарантируется: http://stackoverflow.com/questions/27669200/how-should-i-brace-initialize-an-stdarray-of-stdpairs#comment43754338_27669457. – marcinj

5

Это стало бы возможным, так как C++ 17, из что для некоторых конкретных случаев copy elision гарантируются ,

При следующих обстоятельствах составители должны опускать от копирования и MOVE- Конструкторы класса объектов, даже если копировать/перемещать конструктор и деструктор имеют наблюдаемые побочные эффекты:

  • В инициализации, если выражение инициализатора является prvalue, а cv-неквалифицированная версия типа источника - это тот же класс, что и класс назначения , выражение инициализатора используется для инициализировать целевой объект:

    T x = T(T(T())); // only one call to default constructor of T, to initialize x 
    

И для этих случаев, копировать/перемещать конструктор не должен быть доступен.

When copy-elision takes place (until C++17)In those cases where copy-elision is not guaranteed, if it takes place (since C++17) и от копирования/перемещения-конструктор не вызывается, то он должен присутствовать и доступны (как если бы оптимизация не происходило вообще), в противном случае программа плохо сформированным.

LIVE