Подтвердить что ты не робот

Различное поведение компилятора при применении спецификатора const к аргументу шаблона

Рассмотрим следующий пример (godbolt):

#include <iostream>

template <typename T>
const T *as_const(T *p) { return p; }

void f() {}

template <typename T>
void g(T *) { std::cout << "A"; }

template <typename T>
void g(const T *) { std::cout << "B"; }

int main() {
  g(as_const(&f));
}

Как GCC, так и Clang могут скомпилировать его, но полученные в результате исполняемые файлы производят другой вывод: версия, скомпилированная с GCC-отпечатками A и скомпилированная с помощью Clang-распечаток B

Не могли бы вы объяснить эту разницу?

Обновление: как указано в @VTT, наблюдается такая же разница, даже если as_const отбрасывается.

4b9b3361

Ответ 1

Похоже, вы попали в дефект в стандарте, который еще предстоит решить. Итак, ответ на вопрос: "Какой компилятор прав?" в настоящее время не совсем ясны.

Этот вопрос был поднят и обсужден комитетом:

Неясно, правильно ли сформировано следующее:

void foo(){}

template<class T>
void deduce(const T*) { }

int main() {
  deduce(foo);
}

Реализации различаются в их отношении к этому примеру.

см. http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1584, но предлагаемая резолюция не является частью N4141 или N4659.

Обратите внимание, что вы вообще не можете иметь указатели на типы функций const; если вы рассмотрите пример, который я назвал плохо сформированным, gcc будет правильным. Он отвергает пример и в OP выбирает неконстантную версию как единственную жизнеспособную перегрузку.

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

Тем не мение,

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

(примечание к указанной проблеме), похоже, указывает на то, что gcc прав, и проблема будет решена в пользу его поведения.