Тип вывода в коммутаторе и SFINAE, gcc vs clang [duplicate]

Я бы рекомендовал использовать брелки. Используя Keychain, вы можете сохранить свой пароль в зашифрованном виде. Взгляните на образец Apple GenericKeychain .

NSUserDefaults немного менее безопасен по сравнению с Keychain. В NSUserDefaults данные могут легко получить доступ, если известен конкретный ключ. Это не относится к Keychain.

Вы также можете преобразовать NSUserDefaults в Keychains. Посмотрите здесь .

26
задан Community 23 May 2017 в 11:44
поделиться

6 ответов

В моем суматошном мнении и на основе §13.3.3 / 1 Наилучшая жизнеспособная функция [over.match.best] , оператор перегруженного преобразования без шаблона (т. е. operator int() const) имеет более высокий приоритет в отношении выбора разрешения перегрузки, чем его шаблонный аналог (т. е. template <typename T> operator T () const).

Таким образом, перегруженное разрешение правильно выбрало бы operator int() const по сравнению с template <typename T> operator T () const, поскольку является наилучшей жизнеспособной функцией.

Кроме того, поскольку версия без шаблона будет выбрана над шаблоном (т. е. шаблон не будет материализован / квалифицирован компилятором), class Var будет иметь одну функцию преобразования, и, следовательно, требование в §6.4.2 / 2 Оператор switch [stmt.switch] для единственного интегрального преобразования будет выполнен.

Следовательно, Clang прав, а GCC ошибочен.

2
ответ дан 101010 17 August 2018 в 12:22
поделиться
  • 1
    Я не думаю, что предпочтение выбора перегрузки для не-шаблона над эквивалентной сигнатурой, выбранной путем создания шаблона, имеет значение здесь. – David Rodríguez - dribeas 30 July 2014 в 23:14

Вот соответствующие цитаты, но окончательный ответ во многом зависит от интерпретации.

N3797 6.4.2 / 2:

Условие должно быть цельного типа, типа перечисления или типа класса , Если тип класса, условие контекстно неявно преобразуется (раздел 4) в интегральный или перечисляемый тип.

4/5:

Определенные языковые конструкции требуют преобразования в значение, имеющее один из определенного набора типов, соответствующих конструкции. Выражение e типа класса E, появляющееся в таком контексте, называется , контекстно неявно преобразованным в заданным типом T и хорошо сформированным тогда и только тогда, когда e может неявно преобразуется в тип T, который определяется следующим образом: E выполняется поиск функций преобразования, возвращаемым типом которых является cv T или ссылка на cv T, что T разрешено контекстом. Должен быть ровно один такой T.

14.5.2 / 6:

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

14.5.2 / 8:

Разрешение перегрузки (13.3.3.2) и частичное упорядочение (14.5.6.2) используются для выбора наилучшей функции преобразования между несколькими специализациями шаблонов функций преобразования и / или функциями преобразования без шаблона.

Интерпретация 1: 4/5 гласит «функции преобразования», а не «функции преобразования и шаблоны функций преобразования». Поэтому Var::operator int() const является единственным вариантом, а clang является правильным.

Интерпретация 2 [слабый?]: 14.5.2 требует от нас сравнить шаблон функции преобразования путем разрешения перегрузки и частичного упорядочения на том же начальном как функция преобразования без шаблона. Они сравнивают специализированные функции и функции шаблонов, а не шаблоны функций, поэтому мы будем делать вывод аргумента шаблона. Вычисление аргумента шаблона для шаблона функции преобразования требует целевого типа. Хотя у нас обычно есть более четкий тип цели, в этом случае мы просто попробуем (теоретически все) все типы в наборе допустимых типов. Но ясно, что функция без шаблона является лучшей жизнеспособной функцией, которая включает все специализированные шаблоны, поэтому разрешение перегрузки выбирает функцию без шаблона. clang является правильным.

Интерпретация 3: Поскольку для разрешения перегрузки требуется вычет аргумента шаблона, а вывод аргумента шаблона требует известного целевого типа, сначала следует рассмотреть семантику 4/5, а затем ее преобразованный тип (если любой) может использоваться для процесса разрешения перегрузки. 14.5.2 требует рассмотрения шаблона функции преобразования, но затем мы обнаруживаем, что существует несколько допустимых типов T, для которых у нас есть функция преобразования T [эта функция, возможно, является специализированной функцией). Программа плохо сформирована, поэтому g ++ корректна.

2
ответ дан aschepler 17 August 2018 в 12:22
поделиться

Если я правильно читаю этот раздел при перегрузке, Clang корректен

13.3.3 Наилучшая жизнеспособная функция [over.match.best]

[.. .] Учитывая эти определения, жизнеспособная функция F1 определяется как лучшая функция, чем другая жизнеспособная функция F2, если для всех аргументов i ICSi (F1) не является хуже конверсионной последовательностью, чем ICSi (F2), а затем [... ]

- F1 - это функция без шаблона, а F2 - специализированная функция шаблона или, если не это, [...]

Черновик свободен читать. Не уверены, были ли внесены изменения в 13.3.3 в окончательную спецификацию (я не заплатил за нее)

http://www.open-std.org/jtc1/sc22/ wg21 / docs / papers / 2012 / n3337.pdf

Я бы установил ошибку G ++ :-) Они могут вернуться с другим разделом стандарта, чтобы оправдать, но, похоже, совместимы с нестандартными.

Редактировать комментарий пользователя:

От: http://publib.boulder.ibm.com/infocenter/comphelp/v101v121/index. jsp? topic = / com.ibm.xlcpp101.aix.doc / language_ref / cplr315.html

Предположим, что f является перегруженным именем функции. Когда вы вызываете перегруженную функцию f (), компилятор создает набор функций-кандидатов. Этот набор функций включает в себя все функции с именем f, к которым можно получить доступ из точки, где вы вызвали f (). Компилятор может включать в качестве функции-кандидата альтернативное представление одной из этих доступных функций с именем f для облегчения разрешения перегрузки.

После создания набора функций-кандидатов компилятор создает набор жизнеспособных функций. Этот набор функций является подмножеством функций-кандидатов. Количество параметров каждой жизнеспособной функции согласуется с количеством аргументов, которые вы использовали для вызова f ().

1
ответ дан Caladain 17 August 2018 в 12:22
поделиться
  • 1
    Я не думаю, что преобразование шаблонов в первую очередь жизнеспособно. – aschepler 30 July 2014 в 23:07
  • 2
    Жизнеспособный означает что-то конкретное в контексте соответствия перегрузки. – Caladain 30 July 2014 в 23:10
  • 3
    Да. 13.3.1 / 7: «В каждом случае, когда кандидат является шаблоном функции, специализированные шаблоны функций кандидата генерируются с использованием вычитания аргумента шаблона. Затем эти кандидаты обрабатываются как кандидатные функции обычным способом. Но здесь вывод аргумента шаблона не удастся, поэтому нет никакой специализации в наборе кандидатов, а набор жизнеспособной функции является подмножеством набора кандидатов. – aschepler 30 July 2014 в 23:14
  • 4
    По крайней мере, я спрошу у CPPcon в сентябре и отправлю сюда, если они не ответят на список рассылки до этого :-) – Caladain 31 July 2014 в 02:03

6.4.2 / 2 Оператор switch (выделение)

Условие должно быть целочисленного типа, типа перечисления или типа класса, для которого один неявный существует функция преобразования в интегральный или перечисляемый тип (12.3). Если условие имеет тип класса, условие преобразуется путем вызова этой функции преобразования, а результат преобразования используется вместо исходного условия для остальной части этого раздела.

Поэтому моя интерпретация заключается в том, что g ++ здесь верен.

9
ответ дан iavr 17 August 2018 в 12:22
поделиться
  • 1
    Но проблема в том, что gcc не рассматривает, что оператор преобразования без шаблонов лучше соответствует, по сравнению с версией шаблона, в то время как clang делает. Ваш ответ не затрагивает эту часть. – Praetorian 30 July 2014 в 22:45
  • 2
    @Praetorian в стандарте говорит «a одиночная неявная функция преобразования». Он не говорит, что есть разрешение перегрузки. – Brian 30 July 2014 в 22:46
  • 3
    С другой стороны, можно сделать разумный аргумент, заключающийся в том, что функция преобразования шаблона не считается «интегральным или перечисляемым типом», тем более что T не может быть выведена как какой-либо целочисленный или перечисляемый тип, и в этом случае только одна функция преобразования, которая квалифицируется. – hvd 30 July 2014 в 22:53
  • 4
    Я отправил по электронной почте список рассылки стандартных обсуждений на C ++. Давайте посмотрим, что они думают :-) – Brian 30 July 2014 в 23:02
  • 5
    Является ли шаблон неявным преобразованием в интегральный тип? --Sure: int x = v; char c = v; .... Тот факт, что тип не может быть выведен, не делает его не преобразованием. Обратите внимание, что цитата не говорит в контексте оператора switch или чего-то подобного, она касается только ее существования. – David Rodríguez - dribeas 30 July 2014 в 23:18
17
ответ дан Shafik Yaghmour 17 August 2018 в 12:22
поделиться

Я считаю, что 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 полные проблемы (или, исключая ограничения компилятора, проблему остановки), чтобы определить, следует ли компилировать прогрму или нет.

Я не знать правильную формулировку. Но формулировка, как написано, не звучит.

3
ответ дан Yakk - Adam Nevraumont 17 August 2018 в 12:22
поделиться
  • 1
    Как operator T() может иметь предложение SFINAE, и все еще можно использовать? – aschepler 31 July 2014 в 01:29
  • 2
    @aschepler template<class T,class=std::enable_if_t<T::bob==2>> operator T() – Yakk - Adam Nevraumont 31 July 2014 в 01:44
  • 3
    @aschepler хм. Недопустимый operator long<long,void>() может испортить мой план: он существует, и SFINAE не может блокировать его существование. Таким образом, это может только занять его уродливую голову, когда приходят идеи lite. Хм. – Yakk - Adam Nevraumont 31 July 2014 в 01:52
  • 4
    В чем проблема с operator long<long, void>()? Что существуют шаблонные аргументы, чтобы замена была успешной? Как насчет template<class T, std::enable_if_t<T::bob==2>* = nullptr> operator T()? – dyp 31 July 2014 в 20:52
  • 5
    @ T.C. хе. Который может быть, почему Шафик прав, как мог бы быть. – Yakk - Adam Nevraumont 1 August 2014 в 21:46
Другие вопросы по тегам:

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