Лучший способ обхода ошибки компилятора C2158: make_public не поддерживает собственные типы шаблонов

У меня есть две библиотеки DLL c ++ / cli (т. Е. Скомпилированные с / clr), где A.dll ссылается на B.dll. В сборке B у меня есть метод GetMgdClassB, который я хотел бы вызвать из сборки A. Вот код сборки B (B.cpp):

namespace B
{
    public class NativeClassB
    {
    public:
        NativeClassB();
        // ... 
    };

    public ref class MgdClassB
    {
    public:
        static MgdClassB ^ GetMgdClassB(const std::vector & vecNativeBs)
        {
            // ...
            vecNativeBs;
            return gcnew MgdClassB();
        }
    };
}

Обратите внимание, что метод GetMgdClassB принимает std :: vector. В сборке A я пытаюсь вызвать этот метод с помощью следующего кода (A.cpp):

namespace B
{
    class NativeClassB;
}

#pragma make_public(std::vector)

namespace A
{
    void Foo()
    {
        std::vector vecNativeBs;
        B::MgdClassB::GetMgdClassB(vecNativeBs);
    }
}

Когда я компилирую A.cpp, я получаю следующую ошибку:

error C2158: 'std::vector<_Ty>' : #pragma make_public directive is currently supported for native non-template types only

причина, по которой я хотел добавить эту прагму, заключается в том, что встроенная по умолчанию типы являются частными для сборки. Если я удалю прагму, я получу следующую ошибку (как и ожидалось):

error C3767: 'B::MgdClassB::GetMgdClassB': candidate function(s) not accessible

, поскольку тип создания шаблона std :: vector является частным для сборки.

Попытка Решения

1. Используйте void *, безопасность типа прерывания:

Измените метод, GetMgdClassB , чтобы взять void * и передать в метод адрес std :: vector . В GetMgdClassB . Затем я могу static_cast передать в void * в std :: vector * . Это, конечно, работает, но нарушает безопасность типов.

2. Создайте управляемую оболочку для NativeClassB, передайте управляемый контейнер

Создайте управляемый класс, скажем ref class NativeClassBWrapper , единственная цель которого - сохранить ссылку на собственный NativeClassB. Измените GetMgdClassB, чтобы он использовал управляемый контейнер NativeClassBWrappers (например, List ^ ).

В настоящее время я склоняюсь к решению №1, поскольку (а) оно не вызывает никаких проблем с производительностью и (б) я буду делать это только в нескольких случаях. Мне не нравится терять безопасность типов, но это кажется оправданным, учитывая текущий недостаток способности компилятора делать видимыми типы экземпляров собственных шаблонов.

Вопрос:

Есть ли лучшие решения?

Связанный вопрос:

Ошибка CLI C ++ C3767: функции-кандидаты недоступны

5
задан Community 23 May 2017 в 12:04
поделиться