Я считаю, что gcc корректен, но стандарт ошибочен.
gcc корректен, потому что стандарт задает один неявный оператор преобразования для целых или перечисляемых типов для типов, используемых в switch
.
Стандарт неверен, поскольку обнаружение этого случая связано с решением проблемы остановки.
operator T
может иметь приложенное к нему предложение SFINAE произвольной сложности. Компилятор под стандартом должен определить, есть ли T
, чтобы T
был enum
.
template<class...Ts>
struct evil {
enum { bob = 3+sizeof...(Ts) };
};
struct test {
operator int() const { return -1; };
template<class T, typename std::enable_if<T::bob==2>::type* unused=nullptr>
operator T() const { return T::bob; }
};
int main() {
switch( test{} ) {
case -1: std::cout << "int\n"; break;
case 2: std::cout << "bob\n"; break;
default: std::cout << "unexpected\n"; break;
}
}
Вышеприведенный код демонстрирует случай, когда мы имеем бесконечное число из enum
s неявно доступны. У нас есть operator T
, который будет отличать тип T
тогда и только тогда, когда T::bob==2
. Теперь в нашей программе нет таких enum
s (и даже если бы мы удалили 3+
, все равно этого не было бы, потому что это не enum class
- легко исправлено).
Таким образом, test
может быть преобразован только в int
, и поэтому инструкция switch
должна компилироваться. gcc отказывает в этом тесте и утверждает, что template operator T
делает его неоднозначным (не сообщая нам, что T
, естественно).
Замена enum type
на enum class type
, и удаление 3+
делает switch
заявление не соответствует стандарту. Но для компилятора, чтобы понять это, он в основном должен создать все возможные шаблоны в программе, которые ищут секрет enum
с соответствующим свойством. С небольшой работой я могу заставить компилятор решить NP полные проблемы (или, исключая ограничения компилятора, проблему остановки), чтобы определить, следует ли компилировать прогрму или нет.
Я не знать правильную формулировку. Но формулировка, как написано, не звучит.
Экземпляр AudioAttributes построен через его конструктор AudioAttributes.Builder.
Вы можете использовать его следующим образом.
sp21.setAudioAttributes(new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build());
Ссылка: https: / /developer.android.com/reference/android/media/AudioAttributes.html
У меня есть что добавить. Я использовал SoundPool в своем игровом приложении для воспроизведения небольших и простых аудиофайлов ogg. Он работал нормально даже на эмуляторах с API 21. Сегодня я решил изменить его, чтобы использовать SoundPool.Builder ().
Я посмотрел на документ SoundPool.Builder от Android. Там сказано
public static class
SoundPool.Builder
extends Object
java.lang.Object
↳ android.media.SoundPool.Builder
Class Overview
Builder class for SoundPool objects.
Обратите внимание на строку «Класс Builder для объектов SoundPool». Поэтому SoundPool.Builder () создает объект SoundPool. SoundPool () также создает объект SoundPool. Так вот что я сделал.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
AudioAttributes audioAttrib = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_GAME)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
mSound = new SoundPool.Builder().setAudioAttributes(audioAttrib).setMaxStreams(6).build();
}
else {
mSound = new SoundPool(6, AudioManager.STREAM_MUSIC, 0);
}
mSound объявлено как
private SoundPool mSound;
Остальная часть кода (где я загружаю, воспроизвожу, останавливаю, отпускаю звук) остается точно такой же, как раньше. И он работает в API 21 и более ранних версиях
Надеюсь, это поможет вам всем