not необходимо поместить реализацию в файл заголовка, см. альтернативное решение в конце этого ответа.
В любом случае причина, по которой ваш код не работает, что при создании экземпляра шаблона компилятор создает новый класс с заданным аргументом шаблона. Например:
template
struct Foo
{
T bar;
void doSomething(T param) {/* do stuff using T */}
};
// somewhere in a .cpp
Foo f;
При чтении этой строки компилятор создаст новый класс (назовем его FooInt
), что эквивалентно следующему:
struct FooInt
{
int bar;
void doSomething(int param) {/* do stuff using int */}
}
Следовательно, компилятор должен иметь доступ к реализации методов, чтобы создать экземпляр с аргументом шаблона (в данном случае int
). Если эти реализации не были в заголовке, они не были бы доступны, поэтому компилятор не смог бы создать экземпляр шаблона.
Общим решением для этого является запись объявления шаблона в заголовок файла, затем реализовать класс в файле реализации (например, .tpp) и включить этот файл реализации в конец заголовка.
// Foo.h
template
struct Foo
{
void doSomething(T param);
};
#include "Foo.tpp"
// Foo.tpp
template
void Foo::doSomething(T param)
{
//implementation
}
Таким образом, реализация по-прежнему отделена от объявления, но доступен компилятору.
Другое решение состоит в том, чтобы сохранить реализацию отдельно и явно создать все экземпляры шаблона, которые вам понадобятся:
// Foo.h
// no implementation
template struct Foo { ... };
//----------------------------------------
// Foo.cpp
// implementation of Foo's methods
// explicit instantiations
template class Foo;
template class Foo;
// You will only be able to use Foo with int or float
Если мое объяснение isn ' t достаточно ясно, вы можете взглянуть на C ++ Super-FAQ по этому вопросу .
Проблема в том, что я не был подключен к сети, поэтому Google Фото не удалось получить выбранное изображение. См. Мой ответ на @ adityakamble49.
Используйте ACTION_GET_CONTENT Intent Action - Intent.ACTION_GET_CONTENT
Вызов после selectImage()
метода для запуска выбора изображения Intent, в котором будут отображаться все приложения, доступные для выбора изображения из
private val RC_SELECT_IMGAE = 101
private fun selectImage() {
val selectImageIntent = Intent(Intent.ACTION_GET_CONTENT, MediaStore.Images.Media
.EXTERNAL_CONTENT_URI)
startActivityForResult(selectImageIntent, RC_SELECT_IMGAE)
}
Затем обработайте обратный вызов путем переопределения метода onActivityResult()
в Activity
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
RC_SELECT_IMGAE -> {
if (data != null) {
val uri = data.data
displaySelectedImage(getBitmapFromUri(uri))
}
}
else -> super.onActivityResult(requestCode, resultCode, data)
}
}
Наконец, обновите представление изображения с помощью растрового изображения, как показано ниже
private fun getBitmapFromUri(uri: Uri): Bitmap {
val parcelFileDescriptor = contentResolver.openFileDescriptor(uri, "r")
val fileDescriptor = parcelFileDescriptor?.fileDescriptor
val image = BitmapFactory.decodeFileDescriptor(fileDescriptor)
parcelFileDescriptor.close()
return image
}
private fun displaySelectedImage(imageBitmap: Bitmap) {
iv_selected_image.setImageBitmap(imageBitmap)
}
Найдите рабочий пример выбора изображения здесь - ImagePickerExample
Вы можете добавить FileProvider
в случае, если он дает какой-либо URI Exception
Попробуем вот так:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
} else {
intent = new Intent(Intent.ACTION_GET_CONTENT);
}