Две различные реализации одного и того же конструктора шаблонов с использованием SFINAE [duplicate]

(не требуется корень) Существует один лучший, простой и с UI-методом для Android Studio

IntelliJ и Android Studio, созданный для быстрого подключения вашего устройства Android через Wi-Fi к устанавливать, запускать и отлаживать приложения без подключения USB. Нажмите одну кнопку и забудьте о своем USB-кабеле.

просто установите плагин Android WiFi ADB

Загрузите и установите Android WiFi ADB прямо из

Intellij / Android Studio: Настройки / Настройки-> Плагины-> Обзор репозиториев

.

Помните! в первый раз для инициализации устройства вам необходимо подключиться с помощью usb

. Кроме того, вы можете загрузить плагин с сайта плагина JetBrains и установить его вручную в: Настройки / Настройки-> Плагины-> Установить плагин из диск.

Вы можете легко подключать и управлять своими устройствами ....... для получения дополнительной информации читайте здесь https://github.com/pedrovgs/AndroidWiFiADB

18
задан undermind 8 April 2016 в 11:59
поделиться

5 ответов

Я думаю, проблема заключается в том, что вы можете использовать функцию, даже если параметр шаблона по умолчанию не компилируется, указав для него другое значение. Подумайте, что произойдет, если вы указали два параметра шаблона в вызове для добавления.

1
ответ дан Dani 28 August 2018 в 02:59
поделиться

SFINAE не распространяется на значения по умолчанию для любых типов или значений. В этом методе используются только типы аргументов и результатов функции.

0
ответ дан Lapshin Dmitry 28 August 2018 в 02:59
поделиться

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

У вас есть две функции, объявленные как таковые:

void foo(int _arg1, int _arg2 = 3);

И

void foo(int _arg1, int _arg2 = 4);

Надеюсь, вы поймете, что это не скомпилируется, их никогда не будет для того, чтобы отличить два вызова к foo с аргументом по умолчанию. Это полностью неоднозначно, как компилятор когда-либо узнает, какой вариант по умолчанию выбрать? Вы можете задаться вопросом, почему я использовал этот пример, ведь шаблон шаблона в первом примере не выводит разные типы? Короткий ответ на это - нет, и это потому, что «подпись» двух шаблонов в вашем втором примере:

template<
    typename T, 
    typename = typename std::enable_if<std::is_same<T, int>::value, T>::type>
void Add(T) {}

template<
    typename T, 
    typename = typename std::enable_if<!std::is_same<T, int>::value, T>::type>
void Add(T) {}

... имеет ту же самую подпись, которая есть:

template<typename T,typename>
void Add(T);

И (соответственно)

template <typename T, typename>
void Add(T); 

Теперь вы должны начать понимать сходство между примером, который я дал с не-шаблонами, и примером, который вы предоставили, что не удалось.

1
ответ дан Nowhere Man 28 August 2018 в 02:59
поделиться

Здесь проблема заключается в том, что сигнатура шаблона для add() одинакова: шаблон функции с двумя типами параметров.

Итак, когда вы пишете:

template<
    typename T, 
    typename = std::enable_if_t<std::is_same<T, int>::value, T>>
void Add(T) {}

Это нормально, но когда вы пишете:

template<
    typename T, 
    typename = std::enable_if_t<!std::is_same<T, int>::value, T>>
void Add(T) {}

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

Если вы хотите, чтобы несколько реализаций, как ваш вопрос, предлагали, вы должны использовать std::enable_if_t в качестве возвращаемого параметра вашего шаблона или использовать его таким же образом, как ваш первый пример. Таким образом, ваш начальный код становится:

template<typename T>
std::enable_if_t<std::is_same<T, int>::value> Add(T) {}
template<typename T>
std::enable_if_t<!std::is_same<T, int>::value> Add(T) {}

Рабочий пример в Coliru

В коде выше, если T == int, вторая подпись становится недействительной и который запускает SFINAE.

NB: Предположим, что вам нужны N реализаций. Вы можете использовать тот же трюк, что и выше, но вам нужно убедиться, что только один логический из N является истинным, а N-1, который остается ложным, в противном случае вы получите ту же самую ошибку!

2
ответ дан Rerito 28 August 2018 в 02:59
поделиться

SFINAE - это замена. Итак, заменим!

template<
  typename T, 
  std::enable_if_t<std::is_same<T, int>::value, T>* = nullptr>
void Add(T) {}

template<
  typename T, 
  std::enable_if_t<!std::is_same<T, int>::value, T>* = nullptr>
void Add(T) {}

Становится:

template<
  class T=int, 
  int* = nullptr>
void Add(int) {}

template<
  class T=int, 
  Substitution failure* = nullptr>
void Add(int) {

template<
  class T=double, 
  Substitution failure* = nullptr>
void Add(double) {}

template<
  class T=double
  double* = nullptr>
void Add(double) {}

Удаляет ошибки, которые мы получаем:

template<
  class T=int, 
  int* = nullptr>
void Add(int) {}
template<
  class T=double
  double* = nullptr>
void Add(double) {}

Теперь удаляет значения параметров шаблона :

template<
  class T, 
  int*>
void Add(T) {}
template<
  class T
  double*>
void Add(T) {}

Это разные шаблоны.

Теперь тот, который испортился:

template<
  typename T, 
  typename = typename std::enable_if<std::is_same<T, int>::value, T>::type>
void Add(T) {}

template<
  typename T, 
  typename = typename std::enable_if<!std::is_same<T, int>::value, T>::type>
void Add(T) {}

Становится:

template<
  typename T=int, 
  typename =int>
void Add(int) {}

template<
  typename int, 
  typename = Substitution failure >
void Add(int) {}

template<
  typename T=double, 
  typename = Substitution failure >
void Add(double) {}

template<
  typename T=double, 
  typename = double>
void Add(double) {}

Удалять сбои:

template<
  typename T=int, 
  typename =int>
void Add(int) {}
template<
  typename T=double, 
  typename = double>
void Add(double) {}

И теперь значения шаблона шаблона:

template<
  typename T, 
  typename>
void Add(T) {}
template<
  typename T, 
  typename>
void Add(T) {}

Это одна и та же подпись шаблона. И это не разрешено, генерируется ошибка.

Почему такое правило? Помимо объема этого ответа. Я просто демонстрирую, как эти два случая отличаются друг от друга, и утверждая, что стандарт рассматривает их по-разному.

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

17
ответ дан Yakk - Adam Nevraumont 28 August 2018 в 02:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: