2015-09-04 3 views
26

Учитывая две программы, где единственная разница в исходном коде - наличие или отсутствие одного constexpr, возможно ли, что значение программы изменится?Можете добавить «constexpr» изменить поведение?

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

Представьте, что вы имеете дело с кодовой базой, в которой первоначальный разработчик забыл включить constexpr в места, где это было возможно, возможно, код написан до C++ 11. Было бы здорово, если бы компилятор вывел constexpr, чтобы помочь вам справиться с вашей работой. Конечно, возможно, он также должен предупреждать каждый раз, когда он делает это заключение, и побуждает вас явно добавить constexpr. Но это было бы полезно. Мое беспокойство в том, что это может нарушить ситуацию?

До сих пор я могу думать только о том, что функции constexpr неявно inline, и могут быть ситуации, когда добавление inline может изменить ситуацию в плохом режиме; например, если вы нарушите правило с одним определением.

+0

Ну, например, если поставщики компилятора решили отмечать функции, не отмеченные в стандарте как constexpr, которые могут вызвать различное поведение через SFINAE, поэтому именно это было в конечном итоге не разрешено, см. [Является ли это совместимым расширением компилятора для обработки не- -constexpr стандартная библиотека выполняет функции constexpr?] (http://stackoverflow.com/q/27744079/1708801) –

+0

Спасибо за это @ShafikYaghmour. Я провел некоторые эксперименты с SFINAE, чтобы попытаться найти расхождение, но я не мог. Я думаю, что мои примеры были слишком упрощенными :) –

+2

У меня есть [пример, где SFINAE прерывается] (http://stackoverflow.com/a/21319414/1708801) из-за различных методов обработки неопределенного поведения в постоянных выражениях. У меня все еще нет ответа, считается ли это подходящим или нет. Не совсем то же самое, но мы можем видеть, как разные реализации могут разорвать SFINAE. –

ответ

12

Существует простой трюк:

template<int n>struct i{}; 
int foo(int){return 0;} 
constexpr int foo(char){return 'a';} 

template<class T=int, T x=1,i<foo(x)>* =nullptr> 
bool bar(){return true;} 
template<class T=int, T x=1,class...Ts> 
bool bar(Ts...){return false;} 

если int foo(int) является constexpr, другая перегрузка bar выбирается по умолчанию.

При использовании другого кода может произойти любое изменение поведения.

live example (просто измените, что #define X закомментировано).


Дизайн Например:

Перегрузка char предотвращает код выше от того плохо формируется, никаких диагностическое не требуется, так как все шаблоны должны иметь действительную специализацию. foo<char> принадлежности это. На практике его существование не требуется: ADL может найти foo издалека, перегруженный на some_type*, затем пройдите some_type* как T. Это означает, что никакая единица компиляции не может доказать, что код плохо сформирован.

Ts... делает это bar перегрузка менее предпочтительной. Поэтому, если первый соответствует, нет никакой двусмысленности. Только если первый из них не соответствует (из-за SFINAE, вызванного foo(x), не являющегося constexpr), вызывает ли вторая перегрузка (или, если, скажем, кто-то передал ей аргументы).

+0

Perfect. Я изо всех сил пытался сделать что-то, что продемонстрировало «constexpr'-зависимое поведение как в clang, так и в g ++. Но это делает трюк как с clang 3.5.0, так и с g ++ 5.2.0. –

+0

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

+2

@AaronMcDaid Ошибка в непосредственном контексте, поэтому мы получаем отказ замены вместо ошибки. SFINAE означает, что почти любое изменение «подписи» (даже существование!) Может привести к другому поведению во время компиляции и времени выполнения на C++ и делает почти расширения любого интерфейса невозможным для полного соответствия. Однако случаи, когда это происходит (в каждом случае я видел это, в том числе выше) * патологический *. – Yakk

4

Учитывая две программы, в которых единственное различие в исходном коде является наличие или отсутствие одного constexpr, возможно, что смысл изменений программы?

Да, это, по крайней мере, верно для функций constexpr. Именно по этой причине реализациям не разрешено выбирать, какие стандартные функции отмечены как constexpr, основная проблема заключается в том, что пользователи могут наблюдать разные поведения через SFINAE. Это отражено в LWG issue 2013: Do library implementers have the freedom to add constexpr?, который говорит (курсив мой):

Некоторые опасения, высказанные при представлении полной комиссии для голосования к статусу РГ, что этот вопрос был решен без достаточного мысли о последствиях для расходящихся библиотечные реализации, , поскольку пользователи могут использовать SFINAE для наблюдения за другим поведением от идентичного кода. Проблема вернулась к статусу обзора и будет снова обсуждена в Портленде с большей группой. Примечание для Портленда: John Spicer согласился представить озабоченность Core во время любого такого обсуждения в LWG.

+1

@AaronMcDaid Я на самом деле пытаюсь сделать живой пример, прошло некоторое время с тех пор, как я посмотрел на этот код, и я хочу убедиться, что данные верны. –

+0

Это верно для функций 'constexpr' в конкретном. Кроме того, 'constexpr' имеет и другие виды использования, поэтому я бы сказал, что это частично верно. – edmz

+0

(Я только что удалил более ранний комментарий, который я сделал по этому вопросу, поскольку я еще не могу использовать его для создания примера, где изменения поведения из-за наличия 'constexpr') –