Android NDK Error: no matching member function for call to 'push_back'?

Возникла проблема во время портирования своей игры на андроид. Компилятор Android NDK ругается на эту строку:
if(b==13) rock.push_back({(uint16_t)(x*64),(uint16_t)(y*64),0,0});

Вывод компилятора:
spoiler
FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:externalNativeBuildDebug'.
> Build command failed.
  Error while executing process /Android/NDK/ndk-build with arguments {NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=/media/files/Android/project/app/jni/Android.mk NDK_APPLICATION_MK=/media/files/Android/project/app/jni/Application.mk APP_ABI=mips NDK_ALL_ABIS=mips NDK_DEBUG=1 APP_PLATFORM=android-14 NDK_OUT=/media/files/Android/project/app/build/intermediates/ndkBuild/debug/obj NDK_LIBS_OUT=/media/files/Android/project/app/build/intermediates/ndkBuild/debug/lib APP_PLATFORM=android-14 /media/files/Android/project/app/build/intermediates/ndkBuild/debug/obj/local/mips/libmain.so}
  /media/files/Android/NDK/build/core/setup-app.mk:81: Android NDK: Application targets deprecated ABI(s): mips    
  /media/files/Android/NDK/build/core/setup-app.mk:82: Android NDK: Support for these ABIs will be removed in a future NDK release.    
  Android NDK: WARNING: Unsupported source file extensions in /media/files/Android/project/app/jni/src/Android.mk for module main    
  Android NDK:   FC/SDL_FontCache.h    
  [mips] Compile++      : main <= main.cpp
  In file included from /media/files/Android/project/app/jni/src/main.cpp:1:
  In file included from /media/files/Android/project/app/jni/src/include.h:113:
  /media/files/Android/project/app/jni/src/game.cpp:45:39: error: no matching member function for call to 'push_back'
              if(b==13)            rock.push_back({(uint16_t)(x*64),(uint16_t)(y*64),0,0});
                                   ~~~~~^~~~~~~~~
  /media/files/Android/NDK/sources/cxx-stl/llvm-libc++/include/vector:677:36: note: candidate function not viable: cannot convert initializer list argument to 'const std::__ndk1::__vector_base<rck, std::__ndk1::allocator<rck> >::value_type' (aka 'const rck')
      _LIBCPP_INLINE_VISIBILITY void push_back(const_reference __x);
                                     ^
  /media/files/Android/NDK/sources/cxx-stl/llvm-libc++/include/vector:680:36: note: candidate function not viable: cannot convert initializer list argument to 'std::__ndk1::vector<rck, std::__ndk1::allocator<rck> >::value_type' (aka 'rck')
      _LIBCPP_INLINE_VISIBILITY void push_back(value_type&& __x);
                                     ^

класс rck:
class rck{
public:
    unsigned short x,y;
    void show();
    int tm=0;
    uint8_t type=0;
};
//////////////////////
std::vector<rck> rock;

НО! g++ прекрасно компилирует этот код, а Android NDK выдает ошибку. Почему так происходит и как исправить эту ошибку?
  • Вопрос задан
  • 101 просмотр
Решения вопроса 1
@MarkusD Куратор тега C++
все время мелю чепуху :)
class rck{
public:
    unsigned short x,y;
    void show();
    int tm=0;
    uint8_t type=0;
};

Вольное комментирование состояния кода
Тут у нас большие проблемы с читаемостью кода. stdint соседствует с сырыми конструкциями модификации типа, методы вперемешку с полями, класс вместо структуры, использование запятой при объявлении полей, имена в одну букву и акронимы. Неинициализированные поля - распространенный источник ошибок.

Лучше будет с молоду учиться правильно оформлять свой код. Например так.
struct rck final
{
	uint16_t x = 0;
	uint16_t y = 0;
	int32_t tm = 0;
	uint8_t type = 0;
	
	
	void show();
};

Не берусь менять имена, т.к. не понимаю их семантики. Каждое имя должно отражать семантику своего существования или должно быть стерто из кода.


У тебя объявлен, вроде бы, агрегатный тип с неявным конструктором по умолчанию, в котором выполняется инициализация только полей tm и type.

rock.push_back({(uint16_t)(x*64),(uint16_t)(y*64),0,0});

Тут перед обращением к push_back формируется фиктивный std::initializer_list<uint16_t> с двумя элементами внутри.
В общем смысле, до полного списка аргументов нужно указать еще два аргумента. Тогда эту запись можно будет считать агрегатной инициализацией временного объекта типа rck.

Такая форма агрегатной инициализации стандартизирована в C++11. До C++14 агрегатная инициализация отключается для типов, в которых присутствует инициализация полей по месту объявления (в коде это поля tm и type). Каждый следующий стандарт требования к агрегатной инициализации только ужесточает.

GCC давно славится своей слабой поддержкой стандарта языка. Это означает что если код проходит трансляцию g++, это далеко не факт что он соответствует стандарту.
NDK сегодня для сборки использует clang, который на данный момент считается максимально приближенным к стандарту транслятором.

Все это должно дать понять что данный код не соответствует стандарту языка и не должен компилироваться. Подходящего конструктора от двух аргументов для типа rck не определено и тип не является агрегатным.
То, что g++ смог собрать этот код, останется на совести g++.
Еще одним важным моментом будет точное понимание, какой именно стандарт языка выбран для трансляции твоего кода.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы