2015-07-13 13 views
29

W języku JavaScript ES6 dostępna jest funkcja językowa o nazwie destructuring. Istnieje również w wielu innych językach.Jak mogę emulować destructuring w C++?

w JavaScript ES6, wygląda to tak:

var animal = { 
    species: 'dog', 
    weight: 23, 
    sound: 'woof' 
} 

//Destructuring 
var {species, sound} = animal 

//The dog says woof! 
console.log('The ' + species + ' says ' + sound + '!') 

Co mogę zrobić w C++, aby uzyskać podobną składnię i naśladować tego rodzaju funkcjonalność?

+0

W C++ można przeciążać operatorów. Jeśli zdefiniujesz "strukturę" i odpowiednio obciążysz jej operatora przypisania, być może osiągniesz cel, do którego dążysz. Nie jestem pewien. Ale może mógłbyś zbadać ten kierunek. – Elyasin

+1

Sprawdź std :: tie – rici

+0

Python i Ruby również pozwala przypisać do krotek, ale myślę, że ta składnia * Destrukturyzacji * * jest dość unikalna dla JS ... –

Odpowiedz

32

Dla konkretnego przypadku std::tuple (lub std::pair) obiektów, C++ oferuje funkcję std::tie który wygląda podobnie:

std::tuple<int, bool, double> my_obj {1, false, 2.0}; 
// later on... 
int x; 
bool y; 
double z; 
std::tie(x, y, z) = my_obj; 
// or, if we don't want all the contents: 
std::tie(std::ignore, y, std::ignore) = my_obj; 

Nie znam podejścia do zapisu dokładnie tak, jak je przedstawiasz.

+0

Możesz dodać 'make_tie' do' animal', który zwraca 'tie'. – Yakk

+0

Notacja nie jest ważna. Tylko semantyka. Aby być uczciwym, notacja javascript wygląda trochę dziwnie na destrukturyzację. Większość języków używa tylko operatora przecinka: 'x, y = z' lub nawiasy' (x, y) = z' – slebetman

+1

@slebetman Przykład JS niszczy właściwości obiektu. Po prostu użycie zwykłego rozdzielanego przecinkiem byłoby niezdefiniowane, ponieważ klawisze obiektów nie mają porządku. – Kroltan

6

Głównie tam z std::map i std::tie:

#include <iostream> 
#include <tuple> 
#include <map> 
using namespace std; 

// an abstact object consisting of key-value pairs 
struct thing 
{ 
    std::map<std::string, std::string> kv; 
}; 


int main() 
{ 
    thing animal; 
    animal.kv["species"] = "dog"; 
    animal.kv["sound"] = "woof"; 

    auto species = std::tie(animal.kv["species"], animal.kv["sound"]); 

    std::cout << "The " << std::get<0>(species) << " says " << std::get<1>(species) << '\n'; 

    return 0; 
} 
2

Obawiam się, że nie można mieć tego w sposób, do jakiego przyzwyczaiłeś się w JavaScript (a tak przy okazji, wydaje się być new technology in JS). Powodem jest to, że w C++ po prostu nie można przypisać do wielu zmiennych w wyrażeniu struktura/przedmiot/przypisania jak ty w

var {species, sound} = animal 

a następnie użyć species i sound jak prostych zmiennych. Obecnie C++ po prostu nie ma tej funkcji.

Można przypisać do struktur i/lub obiektów podczas przeciążania ich operatora przypisania, ale nie widzę sposobu, w jaki można naśladować to dokładne zachowanie (od dzisiaj). Rozważ inne odpowiedzi oferujące podobne rozwiązania; może to działa na twoją potrzebę.

+0

Istnieją propozycje dodania bardzo blisko składni OP do C++. Ma to niewiele wspólnego z silnym pisaniem. – Yakk

+0

Czy mógłbyś rozwinąć proszę? Również odniesienia byłyby dobre do zrozumienia. W C++ typy muszą * pasować * (w zadaniu). Moim zdaniem jest to bardziej restrykcyjne. Na chwilę obecną oczekuję, że propozycje nie będą się różnić znacznie od innych zamieszczonych tutaj odpowiedzi. – Elyasin

+0

Nie, typy nie muszą pasować do zadania? 'struct foo {void operator = (int x) {std :: cout << x << '\ n';}}; foo f; f = 3;} '? Ani w budownictwie. Czytałem, że ktoś mówi o umożliwieniu "wiązania" konstrukcji "zestawu" (nazwanych) wartości i jakiego rodzaju zmiana składni byłaby wymagana. Ale to cała składnia jest problemem, więcej niż semantyką. – Yakk

1

Inną możliwością mogłoby być wykonane jako

#define DESTRUCTURE2(var1, var2, object) var1(object.var1), var2(object.var2) 

które mogą być użyte, jak:

struct Example 
{ 
    int foo; 
    int bar; 
}; 

Example testObject; 

int DESTRUCTURE2(foo, bar, testObject); 

otrzymując zmienne lokalne foo i bar.

Oczywiście ogranicza się to do tworzenia zmiennych tego samego typu, chociaż przypuszczam, że można użyć do tego celu auto.

To makro jest ograniczone do zrobienia dokładnie dwóch zmiennych. Musisz więc stworzyć DESTRUCTURE3, DESTRUCTURE4 i tak dalej, aby pokryć tak dużo, jak tylko chcesz.

Nie osobiście podoba mi się styl kodowy, który kończy się, ale jest dość zbliżony do niektórych aspektów funkcji JavaScript.

15

w C++ 17 nazywa się to structured bindings, która pozwala na następujące cele:

struct animal { 
    std::string species; 
    int weight; 
    std::string sound; 
}; 

int main() 
{ 
    auto pluto = animal { "dog", 23, "woof" }; 

    auto [ species, weight, sound ] = pluto; 

    std::cout << "species=" << species << " weight=" << weight << " sound=" << sound << "\n"; 
} 
Powiązane problemy