GCC рассматривает эти два объявления функции как эквивалентные:
void F(int* a) { }
void F(int* const a) { }
test.cpp: В функции 'освобождают F (интервал*)':
тест cpp:235: ошибка: переопределение 'пустого F (интервал*)'
тест cpp:234: ошибка: 'освободите F (интервал*)' ранее определенный здесь
Это имеет некоторый смысл, потому что вызывающая сторона будет всегда игнорировать константу, в этом случае... это только влияет на использование параметра внутренняя часть функции.
То, что я задаюсь вопросом, - то, где (если вообще где-нибудь) в стандарте говорится, что нормально специфически отбрасывать спецификаторы на указателях, используемых в качестве аргументов функции в целях разрешения перегрузки.
(Моя реальная проблема - то, что я хотел бы выяснить, где GCC разделяет эти бессмысленные спецификаторы внутренне, и так как C++ frontend GCC замусорен комментариями, ссылающимися на стандарт, соответствующий раздел стандарта мог бы помочь мне найти корректное пятно.)
Стандарт говорит в 8.3,5 / 3, что для целей определения типа функции любые CV-квалификаторы, которые напрямую исключают тип параметра. Я Это буквально говорит, что функция, объявленная как
void foo(int *const a);
, имеет тип функции void (int *)
.
Педантический человек может утверждать, что это не является достаточно окончательно, чтобы утверждать, что вышеуказанная декларация должна соответствовать определению, подобному этому
void foo(int *a)
{
}
или что он должен сделать код с двойной декларацией (как в вашем примере) плохо сформирован, Поскольку ни одна из этих понятий не описан в стандарте в условиях типов функций .
Я имею в виду, мы все знаем, что эти const
были предназначены для игнорирования для всех внешних целей, но до сих пор я не смог найти формулировку в стандарте, который был бы окончательно устойчивым. Может быть, я что-то пропустил.
На самом деле, в 13,1 / 3 он имеет «примечание», в котором говорится, что декларации функций с эквивалентными объявлениями параметров (как определено в 8.3.5), объявляем ту же функцию . Но это просто нота, это не нормативно, что говорит о том, что где-то в стандарте должен быть какой-то нормативный текст по той же проблеме.
Я думаю, что это в основном, как это запрещено, как это:
void foo(int a) {}
void foo(const int a) {}
const на не ссылаются не участвует в перегрузке.
На самом деле вы можете даже объявить
void foo(int a);
и более позднюю очередь
void foo(const int a) {}
, где постоянность является чисто деталей реализации, которую вызывающий абонент не заботится.
Это так же, как:
void foo(int);
void foo(const int);
- одинаково для абонента. Это потому, что функция состоит в том, чтобы получить копию по значению, независимо от того, что, поэтому абонент не заботится, если это считается const
или нет; Это не имеет значения для этого.
Это не Юридическое для компилятора игнорировать такие вещи, но нет разницы в разрешении перегрузки. const
применяется к реализации функции.
Незаконное было бы, если компилятор лечится:
void foo(int i)
{
i = 5; // good
}
void foo(const int)
{
i = 5; // lolwut?
}
то же самое, игнорируя const
.
Я считаю, что все наоборот. Любой указатель, даже неконстантный, можно рассматривать как const :).