map of map of unique_ptr
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 20.05.20 22:21
Оценка:
Господа, подскажите что не так с этим кодом: http://cpp.sh/2rxid

Суть простая: приложение поключается к набору серверов, на каждом сервере есть набор клиентов. Для каждого клиента есть объект, через который приложение с ним работает. Хочу сохранить это все в map<int,map<int,unique_ptr<X>>. Map будет владеть объкетами, при удалении map все объекты долны быть освобождены.

При работе с таким мапом получаю шибку компиляции, которую не могу распарсить.
Re: Copy ctor
От: Qbit86 Кипр
Дата: 20.05.20 22:36
Оценка: +1
Здравствуйте, gandjustas, Вы писали:

G>При работе с таким мапом получаю шибку компиляции, которую не могу распарсить.


Отсутствует конструктор копирования?

error: use of deleted function 'constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const int; _T2 = std::unique_ptr<X>]


Попробуй заменить на shared_ptr<T>.
Глаза у меня добрые, но рубашка — смирительная!
Re: map of map of unique_ptr
От: Sharpeye Россия  
Дата: 20.05.20 23:00
Оценка: 27 (2)
Здравствуйте, gandjustas, Вы писали:

G>При работе с таким мапом получаю шибку компиляции, которую не могу распарсить.


Попробуй заменить
m[a] = {};

на
m[a].clear();
Re[2]: Copy ctor
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 20.05.20 23:01
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>Здравствуйте, gandjustas, Вы писали:


G>>При работе с таким мапом получаю шибку компиляции, которую не могу распарсить.


Q>Отсутствует конструктор копирования?

Q>

error: use of deleted function 'constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const int; _T2 = std::unique_ptr<X>]


Q>Попробуй заменить на shared_ptr<T>.

C shared все ок. Меня интересует что не так с unique_ptr. В теории ничего криминального не делаю, unique_ptr должен работать в std контейнерах, в интернете есть даже примеры.
С shared_ptr наоборот натыкаюсь на рекомендации что лучше так не делать.
Re[2]: map of map of unique_ptr
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 21.05.20 00:01
Оценка:
Здравствуйте, Sharpeye, Вы писали:

S>Здравствуйте, gandjustas, Вы писали:


G>>При работе с таким мапом получаю шибку компиляции, которую не могу распарсить.


S>Попробуй заменить

S>
S>m[a] = {};
S>

S>на
S>
S>m[a].clear();
S>


Первый иф можно вообще убрать, без него прекрасно работает.
Все никак не могу привыкнуть к тому что объекты это не ссылки.
Re: map of map of unique_ptr
От: PM  
Дата: 21.05.20 01:34
Оценка: 37 (5) +2
Здравствуйте, gandjustas, Вы писали:

G>Господа, подскажите что не так с этим кодом: http://cpp.sh/2rxid


G>Суть простая: приложение поключается к набору серверов, на каждом сервере есть набор клиентов. Для каждого клиента есть объект, через который приложение с ним работает. Хочу сохранить это все в map<int,map<int,unique_ptr<X>>. Map будет владеть объкетами, при удалении map все объекты долны быть освобождены.


G>При работе с таким мапом получаю шибку компиляции, которую не могу распарсить.


У типа вложенного map (map<int,unique_ptr<X>>) удален оператор присваивания, т.к. элементы не могут быть присвоены из-за удалённоего оператора присваивания в unique_ptr<X>

В строке 15 m[a] возвращает ссылку на такой неприсваевыемый map, т.е. это
map<int,unique_ptr<X>> default_constructed; // OK
map<int,unique_ptr<X>> & mm = a[m]; // OK
mm = default_constructed; // нельзя, т.к. unique_ptr<X>::operator=() = delete;


В C++ map/unordered_map при доступе по ключу происходит find и вставляется значение по умолчанию, если ключ не найден. Т.е. find() лишний в этом случае. Часто вижу такой код у практикующих Java, там у Map нет метода в стиле insert_or_assign? То же самое, но оптимальнее:
void f(std::map<int, std::map<int,std::unique_ptr<X>>>& m, int a, int b, X x)
{
    auto &mm = m[a];
    mm[b] = std::make_unique<X>(x);
// или даже так
    m[a][b] = std::make_unique<X>(x);
}


Дальше пойдут непрошенные советы, но мы ведь на русском форуме, а не на StackOverflow

С точки зрения компактности хранения и локальности доступа к памяти, map<int,map<int,unique_ptr<X>> это, скорее всего, будет тройной косвенный доступ к экземплярам X.

Вам действительно нужено упорядоченное по ключу перечисление элементов map? Если нет, то возможно стоит для начала рассмотреть использование другого стандартного ассоциативного контейнера unordered_map.

Вы действительно должны динамически создавать и хранить экземпляры X или может быть достаточно храненить их по значению?
Если X — это базовый класс в известной и фиксированной иерархии, а хранить нужно его потомков, то можно рассмотреть использование std::variant<Derived1_from_X, Derived2_from_X, ..> для небольших N.

Вам точно нужнен map of map? Если множество ключей уникально, то составной ключ может быть структурой с определенным operator< для map, или operator== и std::hash для unordered_map:
class X {
};

struct Key
{
    int a;
    int b;

    bool operator==(Key const& key) const
    {
        return a == key.a && b == key.b;
    }
    
    struct hash
    {
        size_t operator()(Key const& key) const
        {
            std::hash<int> const hasher;
            return hasher(key.a) ^ hasher(key.b);
        }
    };
};

using Map = std::unordered_map<Key, X, Key::hash>;

void f(Map& m, int a, int b, X x)
{
    m[Key{a, b}] = std::move(x);
}



Еще нередко бывает, что ключ уже является частью объекта X. Тогда вполне достаточно хранения объектов в set, слава heterogeneous lookup in associative containers. К сожалению, для unordered_set это доступно в стандартной библиотеке только в C++20

struct X
{
    struct Key
    {
        int a;
        int b;
    };

    // object order
    friend bool operator<(X const& x1, X const& x2)
    {
        return std::tie(x1.key_a, x1.key_b) < std::tie(x2.key_a, x2.key_b);
    }

    // transparent less<> for heterogenous lookup    
    friend bool operator<(X const& x, X::Key const& key)
    {
        return std::tie(x.key_a, x.key_b) < std::tie(key.a, key.b);
    }
    friend bool operator<(X::Key const& key, X const& x)
    {
        return std::tie(key.a, key.b) < std::tie(x.key_a, x.key_b);
    }
    
    int key_a;
    int key_b;
    std::string payload;
};

int main()
{
    std::set<X, std::less<>> xs;
    xs.emplace(X{ 1, 2, "large data" });
    xs.emplace(X{ 3, 4, "large data2" });

    auto it = xs.find(X::Key{ 1, 2 });
    std::cout << "{1, 2}: " << it->payload << '\n';
    assert(it->payload == "large data");

    auto it2 = xs.find(X::Key{ 3, 4 });
    std::cout << "{3, 4}: " << it2->payload << '\n';
    assert(it2->payload == "large data2");

    auto it3 = xs.find(X::Key{ 1, 3 });
    assert(it3 == xs.end());
}


Код: https://wandbox.org/permlink/f0wTdZb8SFOhgnxU
Re[3]: Привыкнуть
От: Qbit86 Кипр
Дата: 21.05.20 06:04
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Все никак не могу привыкнуть к тому что объекты это не ссылки.


А с чего вообще взялся за C++? :)
Глаза у меня добрые, но рубашка — смирительная!
Re[3]: Copy ctor
От: Ops Россия  
Дата: 21.05.20 06:08
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>С shared_ptr наоборот натыкаюсь на рекомендации что лучше так не делать.


Лучше так не делать при проблемах с производительностью. Если их нет — делай сколько влезет.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[2]: map of map of unique_ptr
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 21.05.20 08:22
Оценка:
Здравствуйте, PM, Вы писали:

PM>В C++ map/unordered_map при доступе по ключу происходит find и вставляется значение по умолчанию, если ключ не найден. Т.е. find() лишний в этом случае. Часто вижу такой код у практикующих Java, там у Map нет метода в стиле insert_or_assign?

Конечно нет. В других языках вообще не принято неявно вызвать конструкторы. И все контейнеры — ссылочные типы, поэтому дефолт для них — null.

PM>То же самое, но оптимальнее:

PM>
PM>void f(std::map<int, std::map<int,std::unique_ptr<X>>>& m, int a, int b, X x)
PM>{
PM>    auto &mm = m[a];
PM>    mm[b] = std::make_unique<X>(x);
PM>// или даже так
PM>    m[a][b] = std::make_unique<X>(x);
PM>}
PM>

Очень неочевидный код для тех кто работает на других языках.


PM>Дальше пойдут непрошенные советы, но мы ведь на русском форуме, а не на StackOverflow

Собственно ради них сюда и пришел.

PM>С точки зрения компактности хранения и локальности доступа к памяти, map<int,map<int,unique_ptr<X>> это, скорее всего, будет тройной косвенный доступ к экземплярам X.

PM>Вам действительно нужено упорядоченное по ключу перечисление элементов map? Если нет, то возможно стоит для начала рассмотреть использование другого стандартного ассоциативного контейнера unordered_map.
Я, как человек, который не знает C++ выбрал тип, который короче пишется.
unordered_map в данном случае чем лучше обычного map?

PM>Вы действительно должны динамически создавать и хранить экземпляры X или может быть достаточно храненить их по значению?

X это обертка над указателем, возвращаемым функцией COM-объекта, у X есть нетривиальные методы. X владеет этим указателем. Дефолтного конструктора у X нет.
Чтобы X по значению можно было передавать в контейнер надо реализовать конструкторы перемещения (или копировани, я хз), а это для меня, как человека, который не знает C++, оказалось слишком сложно.

Поэтому я и взял unqiue_ptr, потому что я могу ему по факту любой класс передать и получить поведение, которое ожидаю. По крайней мере я так думал пока не попытался сделать map.

PM>Вам точно нужнен map of map? Если множество ключей уникально, то составной ключ может быть структурой с определенным operator< для map, или operator== и std::hash для unordered_map:

map of map выбрал потому что при отключении от сервера можно будет сделать m[x]. clear(). Если
Re[4]: Привыкнуть
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 21.05.20 08:27
Оценка: +1
Здравствуйте, Qbit86, Вы писали:

Q>Здравствуйте, gandjustas, Вы писали:


G>>Все никак не могу привыкнуть к тому что объекты это не ссылки.


Q>А с чего вообще взялся за C++?


В свободное время пилю плагин для игрушки, заодно новшества языка изучаю.
Современный C++ очень выразительный язык, но количество неочевидных проблем зашкаливает. Мне кажется проще чинить утечки памяти в голом C, чем заставить компилироваться нетривиальный код на C++.
Re[3]: map of map of unique_ptr
От: PM  
Дата: 21.05.20 09:46
Оценка: 30 (2) +1
Здравствуйте, gandjustas, Вы писали:

PM>>В C++ map/unordered_map при доступе по ключу происходит find и вставляется значение по умолчанию, если ключ не найден. Т.е. find() лишний в этом случае. Часто вижу такой код у практикующих Java, там у Map нет метода в стиле insert_or_assign?

G>Конечно нет. В других языках вообще не принято неявно вызвать конструкторы. И все контейнеры — ссылочные типы, поэтому дефолт для них — null.

Да, для успешного понимания языка нужно принять тот факт, что в С++ многое основано на значениях, а не на указателях (хранение полей в структурах, передача параметров в/возврат из функции, выбрасывание исключений, RAII, и все контейнеры стандаратной бибилотеки)

PM>>
PM>>void f(std::map<int, std::map<int,std::unique_ptr<X>>>& m, int a, int b, X x)
PM>>{
PM>>    m[a][b] = std::make_unique<X>(x);
PM>>}
PM>>

G>Очень неочевидный код для тех кто работает на других языках.

Но с двумерным массивом код ведь обычно очевиден? map — по сути тоже массив, только может быть с ключами, отличными от целых
void f(std::array<std::array<X, 10>, 10>& matrix, int a, int b, X x)
//     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ читать примерно как X matrix[10][10]
{
   m[a][b] = x;
}



PM>>С точки зрения компактности хранения и локальности доступа к памяти, map<int,map<int,unique_ptr<X>> это, скорее всего, будет тройной косвенный доступ к экземплярам X.

PM>>Вам действительно нужено упорядоченное по ключу перечисление элементов map? Если нет, то возможно стоит для начала рассмотреть использование другого стандартного ассоциативного контейнера unordered_map.
G>Я, как человек, который не знает C++ выбрал тип, который короче пишется.
G>unordered_map в данном случае чем лучше обычного map?

std::map — это binary search tree (реализовано обычно как red-black tree), каждый узел создается динамически, итераторы (указатели на узлы дерева) остаются действительными после вставки/удаления элементов. Следствие реализации — ключи упорядочены, легко искать их диапазоны (см. lower_bound, upper_bound, equal_range)

std::unordered_map — из-за требований стандарта к интерфейсу может быть реализован только как closed addressing hash table. При вставке/удалении элементов итераторы могут стать недействительными (указывать на мусор) из-за re-hashing. Порядок ключей не гарантирован.

Есть сторонние реализации ассоцитивных контенйров, например с отрытой адресацией, или для разреженных ключей. Выбор структуры данных за вами Обычно начинают с map или unordered_map (и в 99% случаях на этом и останавливаются)

PM>>Вы действительно должны динамически создавать и хранить экземпляры X или может быть достаточно храненить их по значению?

G>X это обертка над указателем, возвращаемым функцией COM-объекта, у X есть нетривиальные методы. X владеет этим указателем. Дефолтного конструктора у X нет.
G>Чтобы X по значению можно было передавать в контейнер надо реализовать конструкторы перемещения (или копировани, я хз), а это для меня, как человека, который не знает C++, оказалось слишком сложно.

G>Поэтому я и взял unqiue_ptr, потому что я могу ему по факту любой класс передать и получить поведение, которое ожидаю. По крайней мере я так думал пока не попытался сделать map.



Т.е. сейчас у вас unique_ptr<X> это фактически указатель на указатель типа такого?
X_impl* get_some_X(IComObject* obj);

class X
{
    X_impl* _impl;
public:
   explicit X(IComObject* from_obj)
     : _impl(get_some_X(from_obj)
   {
   }

   void do() { some comlex use of _impl; }
};


Тогда пусть X владеет этим указателем:
class X
{
    std::unique_ptr<X_impl> _impl;
public:
   explicit X(IComObject* from_obj) 
     : _impl(get_some_X(from_obj)
   {
   }

   // если объявлен пользовательский конструктор, то версия по умолчанию сгегерирована не будет
   // но мы можем явно указать компилятору, чтобы он это сделал
   X() = default;

   // копирование будет запрещено из-за некопируемости unique_ptr _impl,
   // но перемещение пусть тоже генерирует компилятор
   X(X&&) = default;
   X& operator=(X&&) = default;
};


PM>>Вам точно нужнен map of map? Если множество ключей уникально, то составной ключ может быть структурой с определенным operator< для map, или operator== и std::hash для unordered_map:

G>map of map выбрал потому что при отключении от сервера можно будет сделать m[x]. clear(). Если

С помощью set::equal_range(Key{x,?}) наверно можно найти все подходящие элементы. Звучит как тестовое задание, надо будет подумать про это

Но в целом да, map of map выглядит понятнее на начальном этапе.
Re: map of map of unique_ptr
От: Мирный герцог Ниоткуда  
Дата: 21.05.20 12:40
Оценка:
Здравствуйте, gandjustas, Вы писали:

безотносительно ошибки компиляции, можно рассмотреть вообще использование unordered_map(pair<int,int>, unique_ptr<t>), т.е. сделать ключом пару id сервера + id клиента.
нормально делай — нормально будет
Re: map of map of unique_ptr
От: andyp  
Дата: 21.05.20 12:44
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>При работе с таким мапом получаю шибку компиляции, которую не могу распарсить.


Там написано, что STL контейнеры предназначены для хранения регулярных типов.
Re[4]: map of map of unique_ptr
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 21.05.20 19:33
Оценка:
Здравствуйте, PM, Вы писали:


PM>Тогда пусть X владеет этим указателем:

PM>
PM>class X
PM>{
PM>    std::unique_ptr<X_impl> _impl;
PM>public:
PM>   explicit X(IComObject* from_obj) 
PM>     : _impl(get_some_X(from_obj)
PM>   {
PM>   }

PM>   // если объявлен пользовательский конструктор, то версия по умолчанию сгегерирована не будет
PM>   // но мы можем явно указать компилятору, чтобы он это сделал
PM>   X() = default;

PM>   // копирование будет запрещено из-за некопируемости unique_ptr _impl,
PM>   // но перемещение пусть тоже генерирует компилятор
PM>   X(X&&) = default;
PM>   X& operator=(X&&) = default;
PM>};
PM>


Я так понимаю что конструктор без параметров обязателен чтобы заработал map<K1, map<K2, X>> ?
Я не хочу его добавлять чтобы у класса не было "нулевого" состояния.
Re[5]: map of map of unique_ptr
От: PM  
Дата: 21.05.20 22:18
Оценка: 21 (1)
Здравствуйте, gandjustas, Вы писали:

G>Я так понимаю что конструктор без параметров обязателен чтобы заработал map<K1, map<K2, X>> ?


Конструктор по-умолчанию в X нужен для map чтобы тот мог вставить значение при обращении к отсутствующему ключу. Вызов find() и
затем insert() если элемент не найден тоже вполне нормальный способ. Это я наверно запутал вас в своем начальном сообщении.

G>Я не хочу его добавлять чтобы у класса не было "нулевого" состояния.


Без проблем, если вам это нужно, при условии что X можно переместить или сконструировать при вставке:
#include <iostream>
#include <map>
#include <memory>
#include <string>
#include <cassert>

class X
{
    std::unique_ptr<std::string> impl_;
public:
    explicit X(std::string const& payload)
        : impl_(std::make_unique<std::string>(payload))
    {
    }
    
    // перемещение все-таки понадобится 
    X(X&&) = default;
    X& operator=(X&&) = default;
    
    std::string const& payload() const { return *impl_; }
};

int main()
{
    std::map<int, std::map<int, X>> m;
    
    // В С++17 есть такой аналог operator[]
    bool inserted = m[1].insert_or_assign(2, X("data")).second;
    assert(inserted);
    inserted = m[1].insert_or_assign(2, X("data2")).second;
    assert(!inserted);

    X const& assigned_x2 = m.at(1).at(2);
    assert(assigned_x2.payload() == "data2");

    auto &mm = m[2];
    inserted = mm.emplace(4, X("data3")).second;
    assert(inserted);
    inserted = mm.emplace(4, X("data4")).second;
    assert(!inserted);
    
    X const& inserted_x4 = mm.at(4);
    assert(inserted_x4.payload() == "data3");
    
    std::cout << m.at(1).at(2).payload() << '\n';

    auto it = m.find(2);
    auto iit = it->second.find(4);
    std::cout << iit->second.payload() << '\n';

    it = m.find(99);
    assert(it == m.end());
}


Код: https://wandbox.org/permlink/5G1xALsrf8LvC9kG
Re[6]: map of map of unique_ptr
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 21.05.20 22:31
Оценка:
Здравствуйте, PM, Вы писали:

PM>Здравствуйте, gandjustas, Вы писали:


G>>Я не хочу его добавлять чтобы у класса не было "нулевого" состояния.


PM>Без проблем, если вам это нужно, при условии что X можно переместить или сконструировать при вставке:

PM>
PM>int main()
PM>{
PM>    std::map<int, std::map<int, X>> m;
    
PM>    // В С++17 есть такой аналог operator[]
PM>    bool inserted = m[1].insert_or_assign(2, X("data")).second;

PM>    X const& assigned_x2 = m.at(1).at(2);
PM>    assert(assigned_x2.payload() == "data2");

PM>    auto &mm = m[2];
PM>    inserted = mm.emplace(4, X("data3")).second;
    
PM>    X const& inserted_x4 = mm.at(4);
PM>}
PM>


1) В чем разница между insert_or_assign и emplace?
2) Правильно понимаю что at кинет исключение если элемент не найден?
3) Как можно сделать так, чтобы конструктор не вызывался, если элемент уже есть в мапе, только через find\if?
Re[7]: map of map of unique_ptr
От: PM  
Дата: 22.05.20 06:07
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>1) В чем разница между insert_or_assign и emplace?

emplace и insert не обновляют значение элемента, если такой ключ уже есть в map
insert_or_assign обновит, если ключ есть, или вставит новое значение, если ключа нет.

При вызове insert создается элемент с ключом и значением, а emplace сначала пытается найти элемент по ключу и только затем создает его (с возможной дополнительной оптимизацией — значение конструируется по месту в узле дерева, без копирования/перемещения)

В предыдущем сообщении я попытался выразить это в коде.

auto it = map.insert({ 1, X{} });  // создается pair{1, X} и перемещается в map
auto it2 = map.insert({ 1, X{} }); // создается pair{1, X} но такой ключ уже есть, только что созданный pair{1, X} уничтожается 

auto it = map.emplace(1, X_args); // find(1) не находит элемент, создается узел в дереве, значение X конструируется из аргументов в созданном узле дерева
auto it2 = map.emplace(1, X_args); // find(1) находит элемент, возвращает итератор на него



G>2) Правильно понимаю что at кинет исключение если элемент не найден?

Да, именно так, я использовал чтобы не проверять ошибки. Это аналог такого кода:
map:::mapped_type map::at(key_type const& key)
{
    auto it = find(key);
    if (it == end()) throw std::out_of_range;
    return it->second;
}


G>3) Как можно сделать так, чтобы конструктор не вызывался, если элемент уже есть в мапе, только через find\if?

Да, или try_emplace() из С++17
auto it = map.find(key);
if (it == map.end())
{
    it = map.insert(pair(key, X(ctor_arg1, .. ctor_argN)));
}

//  или 
it = map.try_emplace(key, ctor_arg1, .. ctor_argN);


Подробнее на https://en.cppreference.com/w/cpp/container/map
Всегда рекомендую этот ресурс, как актальный и полный справочник по С++
Re: map of map of unique_ptr
От: alex_public  
Дата: 22.06.20 19:03
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Господа, подскажите что не так с этим кодом: http://cpp.sh/2rxid

G>Суть простая: приложение поключается к набору серверов, на каждом сервере есть набор клиентов. Для каждого клиента есть объект, через который приложение с ним работает. Хочу сохранить это все в map<int,map<int,unique_ptr<X>>. Map будет владеть объкетами, при удалении map все объекты долны быть освобождены.
G>При работе с таким мапом получаю шибку компиляции, которую не могу распарсить.

Ха! Я тут отпишусь вообще не по теме (по ней уже собственно всё хорошо ответили). Смотрю коллега gandjustas с которым мы не раз сталкивались на этом форуме в дискуссиях типа C++ vs C# и т.п., тоже решил попробовать на своём опыте, каково оно на тёмной стороне... Ну что же, добро пожаловать коллега!
Re[2]: map of map of unique_ptr
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 22.06.20 20:29
Оценка: +1
Здравствуйте, alex_public, Вы писали:

_>Здравствуйте, gandjustas, Вы писали:


G>>Господа, подскажите что не так с этим кодом: http://cpp.sh/2rxid

G>>Суть простая: приложение поключается к набору серверов, на каждом сервере есть набор клиентов. Для каждого клиента есть объект, через который приложение с ним работает. Хочу сохранить это все в map<int,map<int,unique_ptr<X>>. Map будет владеть объкетами, при удалении map все объекты долны быть освобождены.
G>>При работе с таким мапом получаю шибку компиляции, которую не могу распарсить.

_>Ха! Я тут отпишусь вообще не по теме (по ней уже собственно всё хорошо ответили). Смотрю коллега gandjustas с которым мы не раз сталкивались на этом форуме в дискуссиях типа C++ vs C# и т.п., тоже решил попробовать на своём опыте, каково оно на тёмной стороне... Ну что же, добро пожаловать коллега!


Увы, не мой выбор. Делаю плагин к одной софтине, в плагине использую directx. В теории мог бы написать все на C#, но примеров кода на managed нет, а увязывать undamaged с managed выйдет сильно дольше, чем побороть C++ (по крайней мере так кажется). Кроме того требовательность к ресурсам у плагина должна быть минимальная.
Если хотя бы один из факторов отсутствовал — делал бы на C#.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.