Мой код может быть сбой, потому что «класс» не совместим с C? - PullRequest
0 голосов
/ 09 марта 2012

-edit- Я сузил его. Воспроизводимый: почему передача этого объекта в C нарушает мой код?

Мое приложение не работает должным образом после внесения изменений. Я получил предупреждение в MSVC, но не в GCC. Вот репо предупреждения.

предупреждение C4190: для 'fnA' задана C-связь, но возвращается UDT 'Test', который несовместим с C

#include <type_traits> 

template<class T>
class Test{
        T t;
};
typedef Test<int> A;
//static_assert(std::is_pod<A>::value, "Not a POD"); //fails in msvc 2010
static_assert(sizeof(A) == sizeof(int), "");
static_assert(sizeof(A) == sizeof(void*), "");
extern "C" {
        A fnA(A v) { return v; }
}
int main() {
        A a;
        fnA(a);
}

AFAIK не должно быть никаких причин, по которым я не могу использовать Test в качестве возвращаемого значения; Это может не быть проблемой, но это может быть проблемой. Я не могу понять проблему, но я получаю странные странности, которые я не могу воспроизвести (как gcc, так и msvc). Я подозревал, что проблема в том, что MyString поврежден, но, похоже, это не тот случай, который меня очень смутил. Вот моя обертка. MyString> 8 байтов, и мне нужно передать это коду C, который, к сожалению, возвращает все int. Вот почему я поставил static assert, чтобы увидеть, соответствует ли размер класса тому, что я ожидал. Теперь, когда размер / сплайсинг обработан, я все еще как WTF!?! Почему существует это предупреждение, и могу ли я что-нибудь сделать, чтобы это исправить?

Даже запись class Test{ T t; }; вызывает предупреждение, однако структура исправляет его. структура с частными разрывами это, и мне нужно, чтобы быть частным.

OK! После того, как я удалил конструкторы в WrappedPointer и изменил класс на struct (что делает lhs общедоступным). Отлично работает в GCC и MSVC. Изменение struct WrappedPointer на class WrappedPointer нарушает мой код. WTF!?! Это тоже отладочная сборка, не оптимизированная. С какой стати изменение структуры ключевого слова на класс нарушает код!?! WTF!?! НО это изменение не нарушает GCC. Использование конструкторов не по умолчанию break gcc ...

template <class T>
struct WrappedPointer {
//private:
    T* lhs;
public:
    void SetLHS(T*v) { lhs=v; }
    //WrappedPointer(){}
    //WrappedPointer(T*value) : lhs(value){}
    //WrappedPointer(const WrappedPointer&v) : lhs(v.lhs){}
    T* operator->() const { return lhs; }
    T* operator*() const { return lhs; }
    template<class TT>
    bool operator==(TT t) const { return *lhs==t; }
    template<class TT>
    bool operator!=(TT t) const { return *lhs!=t; }

    bool operator==(int v) const { myassert2(v==0); return lhs==0; }
    bool operator!=(int v) const { myassert2(v==0); return lhs!=0; }
    bool operator==(const WrappedPointer&t) const { return *lhs==*t; }
    bool operator!=(const WrappedPointer&t) const { return *lhs!=*t; }
}
typedef WrappedPointer<MyString> String;
//typedef MyString* String;
static_assert(sizeof(String) == sizeof(int), "");
static_assert(sizeof(String) == sizeof(void*),"");

Ответы [ 3 ]

2 голосов
/ 09 марта 2012

external "C" обозначает функцию, которая имеет связь C , а отключает искажение имени.Теперь проблема в вашей функции заключается в том, что аргументом является шаблон (typedef создает только псевдоним в текущей единице перевода, A по-прежнему Test<int> для всех целей), и это имя должен быть искалеченным.

0 голосов
/ 09 марта 2012
  • Классы не действительны в C.
  • Шаблоны недействительны в C.
  • Шаблонные классы, конечно, недопустимы в C.

Выберите свой язык и придерживайтесь его!

0 голосов
/ 09 марта 2012
extern "C" {
    A fnA(A v) { return v; }
}

Это говорит о том, что fnA является функцией C. C не имеет объектно-ориентированного программирования или шаблонов. Функция использует оба. Следовательно, он не может ссылаться как функция C.

...