2016-02-11 11 views
7

Czy można inicjować wiele elementów na liście inicjatora członkowskiego o wartości z krotki uzyskanej przez funkcję?Lista inicjatora elementów: zainicjuj dwa elementy z funkcji zwracającej krotkę

Powracając do wielu wartości, gdy krotki stają się coraz popularniejsze, mam nadzieję, że istnieje na to rozwiązanie. Nie widzę powodu, poza ograniczeniem języka, dlaczego nie byłoby to możliwe.


To mcve za to, co mam:

auto new_foo(std::size_t size) -> std::tuple<std::unique_ptr<char[]>, int*> 
{ 
    auto buffer = std::make_unique<char[]>(size * sizeof(int) + 8); 
    auto begin = static_cast<int*>(static_cast<void*>(buffer.get() + 4)); 
    return std::make_tuple(std::move(buffer), begin); 
} 

struct X { 
    std::unique_ptr<char[]> buffer_{nullptr}; 
    int* begin_{nullptr}; 
    std::size_t size_{0}; 

    X(std::size_t size) : size_{size} 
    { 
     std::tie(buffer_, begin_) = new_foo(size); 
    } 
}; 

Można to zrobić ?:

X(std::size_t size) 
     : buffer_{ ??? }, 
      begin_{ ??? }, 
      size_{size} 
    { 
    } 

ja po prostu nie można nazwać new_foo raz dla każdej inicjalizacji członkowskim (jak to powraca kolejna krotka przy każdym wywołaniu). Więc

X(std::size_t size) 
     : buffer_{std:get<0>(new_foo(size)}, 
      begin_{std:get<1>(new_foo(size)}, 
      size_{size} 
    { 
    } 

nie jest to możliwe (nawet jeśli to nie był przypadek, nazywając kilka razy, aby uzyskać ten sam wynik jest mniejszy niż optymalny)

Innym rozwiązaniem myślałem tylko o tym, aby trzymać członków jak krotka. Odrzuciłem to, ponieważ potrzebowałem dwóch członków poprawnie wymienionych w klasie i nie uzyskano dostępu do nich pod get<0> i.

Kolejnym sposobem obejścia tego problemu jest utworzenie prostej, osobnej struktury, która będzie utrzymywać dwóch członków. W ten sposób będą mieli nazwy, ale dodają kolejny poziom kwalifikatora i możliwe, że będę musiał utworzyć dla niego ctor kopii (z powodu unique_ptr).


Jak donosi hereC++1z będzie miał Structured powiązania (D0144R0), która uczyni to możliwe:

auto {x,y,z} = f(); 

Ponieważ nie mogę znaleźć pełną papier, nie mogę powiedzieć, czy to pomoże w kontekście lista inicjatora elementu. Podejrzewam, że nie.

Odpowiedz

14

Definiowanie innego (prawdopodobnie prywatnego) konstruktora, który bierze krotkę i deleguje do niego.

private: 
    X(std::tuple<std::unique_ptr<char>, int*> t, std::size_t size) 
      : buffer_{std::move(std:get<0>(t))}, 
       begin_{std:get<1>(t)}, 
       size_{size} 
    { } 

public: 
    X(std::size_t size) : X{new_foo(size), size} 
    { } 
Powiązane problemy