Alternatywa dla brace initializer list w c++03

Odpowiedz Nowy wątek
2019-08-07 08:23
0

Cześć,
Borykam się z natępującym problemem.

std::map<std::string, std::vector<uint16_t>>

Zawartość mapy ma być wartością stałą, niemodyfikowaną podczas działania programu.
W normalnych warunkach nie stanowi to problemu, wystarczy użyć brace initialization list.
Problemem jest jednak statyczna analiza kodu, która nie wspiera powyższego rozwiązania, pomimo teoretycznej obsługi c++11 w projekcie(problem nie do przeskoczenia).
Mogę dodawać poszczególne wartości do mapy w ramach pojedyńczej metody, w następujący sposób:

mapa.insert(std::pair<std::string, std::vector<uint16_t>>("arg1", {1, 2, 3}));

Niestety powyższy przypadek wciąż nie unika wykorzystania nawiasów klamrowych.

Czy macie może pomysł jak rozwiązać powyższy problem, bez wykorzystywania długich i bardzo brzydkich konstrukcji?

edytowany 2x, ostatnio: Nunn, 2019-08-07 08:40

Pozostało 580 znaków

2019-08-07 08:57
4

Jeżeli jesteś ograniczony do standardu C++03, to jedynym wyjściem jakie widzę to jest użyć biblioteki boost https://www.boost.org/doc/lib[...]_0/libs/assign/doc/index.html

#include <map>
#include "boost/assign.hpp"
using namespace std;
using namespace boost::assign;

map<string, vector<uint16_t>> mymap = map_list_of ("key1", list_of(1)(2)(3) ) ("key2", list_of(7)(3)(3) ) ("key3", list_of(5)(2)(7) ) ;

Kod wpisałem z pamięci, więc mogą być jakieś błędy związane ze składnią.

Nie da rady. To kod produkcyjny, dodanie boost'a nie przejdzie. - Nunn 2019-08-07 09:11
A tak z ciekawości. Czym jest argumentowana niemożność użycia biblioteki boostowej? - CzarnyPtak 2019-08-07 10:34
To xxx_of to jakies makro? Dziwacznie wyglada - stivens 2019-08-07 10:52
@stivens: raczej metaprogramowanie - vpiotr 2019-08-07 10:58
@CzarnyPtak: To nie jest odpowiedź pytającego a przypadki z jakim ja się spotkałem. "Nie bo nie ma komercyjnego wsparcia do Boost'a". Choć jak ktoś poszuka to znajdzie lub "Nie bo Boost ma nieakceptowalną licencję" do użycia w tym komercyjnym produkcie... - Mokrowski 2019-08-08 16:14
@CzarnyPtak Duże korpo, duży projekt. Nikt nie pozwoli na wprowadzenie boost'a od tak, bo ja chcę. - Nunn 2019-08-09 08:20

Pozostało 580 znaków

2019-08-07 09:20

Jak nie chcesz boosta i nie masz c++11 to możesz ew. sam wszystko zaimplementować:


Szacuje się, że w Polsce brakuje 50 tys. programistów
edytowany 2x, ostatnio: vpiotr, 2019-08-07 09:23
Chyba nie mam innego wyboru niż własna implementacja. - Nunn 2019-08-07 09:46

Pozostało 580 znaków

2019-08-07 14:29
1

Najłatwiej, jeśli to możliwe, po prostu wyłączyć lintera dla tego fragmentu kodu. Np. clang-tidy nie sprawdza linii oznaczonych komentarzem NOLINT:

const std::map<std::string, std::vector<uint16_t>> const_map { // NOLINT
    { "key 0", { 0, 1, 2 } }, // NOLINT
    { "key 1", { 3, 4, 5 } } // NOLINT
}; // NOLINT

IMHO w tym wypadku byłoby to uzasadnione.

Sensowna alternatywa to wzorzec budowniczego:

template<typename KeyType, typename ValueType>
struct MapBuilder
{
    std::map<KeyType, ValueType> result;

    MapBuilder& add(KeyType key, ValueType value)
    {
        result.emplace(std::move(key), std::move(value));
        return *this;
    }
};

template<typename ValueType>
struct VectorBuilder
{
    std::vector<ValueType> result;

    VectorBuilder& add(ValueType value)
    {
        result.push_back(std::move(value));
        return *this;
    }
};

const auto const_map = MapBuilder<std::string, std::vector<uint16_t>>()
    .add("key 0", VectorBuilder<uint16_t>().add(0).add(1).add(2).result)
    .add("key 1", VectorBuilder<uint16_t>().add(3).add(4).add(5).result)
    .result;

Pozostało 580 znaków

2019-08-07 18:27
0
Nunn napisał(a):

Problemem jest jednak statyczna analiza kodu, która nie wspiera powyższego rozwiązania, pomimo teoretycznej obsługi c++11 w projekcie(problem nie do przeskoczenia).

To w końcu jak to jest? Masz to C++11 i tylko statyczna analiza kodu nie radzi sobie z tym przypadkiem? Czy może nie możesz używać C++11?

Jeśli jest to problem ze statyczna analiza kodu to raczej powinieneś opisać jakie to narzędzie i rozważył użycie jakiejś alternatywy.
Nie może być tak, że dostosowujesz kod do braków narzędzia analizy kodu.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.

Pozostało 580 znaków

2019-08-08 15:03
0

Możesz też pokombinować z ranged konstruktorem i tablicami - zamiast iteratorów dajesz wskaźnik na tab[0] i tab[n] (https://en.cppreference.com/w/cpp/container/map/map - wariant nr 2 + to samo dla vectora), ale to nie będzie najwydajniejsze.
Poza tym możesz spróbować użyć std::initializer_list bezpośrednio - jak Ci ten tool to łyknie, to będzie wydajniej niż pomysł powyżej.

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0